Drop netifaces dependency
The netifaces library is no longer maintained, which is why we need to drop this dependency. There is only one place in which netifaces is being used, a trivial function that retrives the mac address for a given ip address. Thankfully, we already have a cloudbase-init "get_adapter_addresses" function that uses ctypes to call GetAdaptersAddresses, which happens to be the same Windows function used by netifaces. Worth mentioning that netifaces is the only compilable cloudbase-init dependency that does not provide a wheel package. Fixes: https://github.com/cloudbase/cloudbase-init/issues/140 Change-Id: Ie52ff722cbf42da7b9bfa9f9942adc1996ce5dd8
This commit is contained in:
parent
dc0367425a
commit
e17488c239
@ -91,6 +91,9 @@ class BaseOSUtils(object):
|
|||||||
def get_network_adapter_name_by_mac_address(self, mac_address):
|
def get_network_adapter_name_by_mac_address(self, mac_address):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def get_mac_address_by_local_ip(self, ip_addr):
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
def set_network_adapter_mtu(self, name, mtu):
|
def set_network_adapter_mtu(self, name, mtu):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
@ -819,6 +819,13 @@ class WindowsUtils(base.BaseOSUtils):
|
|||||||
|
|
||||||
return iface_index_list[0]["friendly_name"]
|
return iface_index_list[0]["friendly_name"]
|
||||||
|
|
||||||
|
def get_mac_address_by_local_ip(self, ip_addr):
|
||||||
|
for iface in network.get_adapter_addresses():
|
||||||
|
addrs = iface.get('unicast_addresses', [])
|
||||||
|
for addr, family in addrs:
|
||||||
|
if ip_addr and addr and ip_addr.lower() == addr.lower():
|
||||||
|
return iface['mac_address'].lower()
|
||||||
|
|
||||||
@retry_decorator.retry_decorator(
|
@retry_decorator.retry_decorator(
|
||||||
max_retry_count=3, exceptions=exception.ItemNotFoundException)
|
max_retry_count=3, exceptions=exception.ItemNotFoundException)
|
||||||
def set_network_adapter_mtu(self, name, mtu):
|
def set_network_adapter_mtu(self, name, mtu):
|
||||||
|
@ -2153,6 +2153,44 @@ class TestWindowsUtils(testutils.CloudbaseInitTestBase):
|
|||||||
self._test_get_network_adapter_name_by_mac_address(
|
self._test_get_network_adapter_name_by_mac_address(
|
||||||
multiple_adapters_found=True)
|
multiple_adapters_found=True)
|
||||||
|
|
||||||
|
@mock.patch("cloudbaseinit.utils.windows.network."
|
||||||
|
"get_adapter_addresses")
|
||||||
|
def test_get_mac_address_by_local_ip(self, mock_get_adapter_addresses):
|
||||||
|
fake_addresses = [
|
||||||
|
{
|
||||||
|
"friendly_name": "mgmt",
|
||||||
|
"mac_address": "24:6E:96:E0:FE:76",
|
||||||
|
"interface_type": 6,
|
||||||
|
"unicast_addresses": [("fe80::499d:b2f9:48c0:c88e%20", 23),
|
||||||
|
("10.11.12.13", 2)],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"friendly_name": "Loopback Pseudo-Interface 1",
|
||||||
|
"mac_address": "",
|
||||||
|
"interface_type": 24,
|
||||||
|
"unicast_addresses": [("::1", 23), ("127.0.0.1", 2)],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
mock_get_adapter_addresses.return_value = fake_addresses
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
"24:6e:96:e0:fe:76",
|
||||||
|
self._winutils.get_mac_address_by_local_ip("10.11.12.13"))
|
||||||
|
self.assertEqual(
|
||||||
|
"24:6e:96:e0:fe:76",
|
||||||
|
self._winutils.get_mac_address_by_local_ip(
|
||||||
|
"fe80::499d:b2f9:48c0:c88e%20"))
|
||||||
|
self.assertEqual(
|
||||||
|
"24:6e:96:e0:fe:76",
|
||||||
|
self._winutils.get_mac_address_by_local_ip(
|
||||||
|
"FE80::499D:B2F9:48C0:C88E%20"))
|
||||||
|
self.assertEqual(
|
||||||
|
"",
|
||||||
|
self._winutils.get_mac_address_by_local_ip("127.0.0.1"))
|
||||||
|
self.assertIsNone(
|
||||||
|
self._winutils.get_mac_address_by_local_ip("10.10.10.10"))
|
||||||
|
|
||||||
@mock.patch('cloudbaseinit.osutils.windows.WindowsUtils'
|
@mock.patch('cloudbaseinit.osutils.windows.WindowsUtils'
|
||||||
'.execute_process')
|
'.execute_process')
|
||||||
@mock.patch('cloudbaseinit.osutils.windows.WindowsUtils'
|
@mock.patch('cloudbaseinit.osutils.windows.WindowsUtils'
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import netifaces
|
|
||||||
import socket
|
import socket
|
||||||
import struct
|
import struct
|
||||||
import unittest
|
import unittest
|
||||||
@ -108,35 +107,19 @@ class DHCPUtilsTests(unittest.TestCase):
|
|||||||
self._test_parse_dhcp_reply(message_type=3, id_reply=111,
|
self._test_parse_dhcp_reply(message_type=3, id_reply=111,
|
||||||
equals_cookie=False)
|
equals_cookie=False)
|
||||||
|
|
||||||
@mock.patch('netifaces.ifaddresses')
|
|
||||||
@mock.patch('netifaces.interfaces')
|
|
||||||
def test_get_mac_address_by_local_ip(self, mock_interfaces,
|
|
||||||
mock_ifaddresses):
|
|
||||||
fake_addresses = {}
|
|
||||||
fake_addresses[netifaces.AF_INET] = [{'addr': 'fake address'}]
|
|
||||||
fake_addresses[netifaces.AF_LINK] = [{'addr': 'fake mac'}]
|
|
||||||
|
|
||||||
mock_interfaces.return_value = ['fake interface']
|
|
||||||
mock_ifaddresses.return_value = fake_addresses
|
|
||||||
|
|
||||||
response = dhcp._get_mac_address_by_local_ip('fake address')
|
|
||||||
|
|
||||||
mock_interfaces.assert_called_once_with()
|
|
||||||
mock_ifaddresses.assert_called_once_with('fake interface')
|
|
||||||
self.assertEqual(fake_addresses[netifaces.AF_LINK][0]['addr'],
|
|
||||||
response)
|
|
||||||
|
|
||||||
@mock.patch('random.randint')
|
@mock.patch('random.randint')
|
||||||
@mock.patch('socket.socket')
|
@mock.patch('socket.socket')
|
||||||
@mock.patch('cloudbaseinit.utils.dhcp._get_mac_address_by_local_ip')
|
|
||||||
@mock.patch('cloudbaseinit.utils.dhcp._get_dhcp_request_data')
|
@mock.patch('cloudbaseinit.utils.dhcp._get_dhcp_request_data')
|
||||||
@mock.patch('cloudbaseinit.utils.dhcp._parse_dhcp_reply')
|
@mock.patch('cloudbaseinit.utils.dhcp._parse_dhcp_reply')
|
||||||
def test_get_dhcp_options(self, mock_parse_dhcp_reply,
|
@mock.patch('cloudbaseinit.osutils.factory.get_os_utils')
|
||||||
|
def test_get_dhcp_options(self, mock_get_os_utils,
|
||||||
|
mock_parse_dhcp_reply,
|
||||||
mock_get_dhcp_request_data,
|
mock_get_dhcp_request_data,
|
||||||
mock_get_mac_address_by_local_ip, mock_socket,
|
mock_socket, mock_randint):
|
||||||
mock_randint):
|
|
||||||
mock_randint.return_value = 'fake int'
|
mock_randint.return_value = 'fake int'
|
||||||
mock_socket().getsockname.return_value = ['fake local ip']
|
mock_socket().getsockname.return_value = ['fake local ip']
|
||||||
|
mock_get_mac_address_by_local_ip = (
|
||||||
|
mock_get_os_utils.return_value.get_mac_address_by_local_ip)
|
||||||
mock_get_mac_address_by_local_ip.return_value = 'fake mac'
|
mock_get_mac_address_by_local_ip.return_value = 'fake mac'
|
||||||
mock_get_dhcp_request_data.return_value = 'fake data'
|
mock_get_dhcp_request_data.return_value = 'fake data'
|
||||||
mock_parse_dhcp_reply.return_value = (True, 'fake replied options')
|
mock_parse_dhcp_reply.return_value = (True, 'fake replied options')
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
import netifaces
|
|
||||||
import random
|
import random
|
||||||
import socket
|
import socket
|
||||||
import struct
|
import struct
|
||||||
@ -21,6 +20,7 @@ import time
|
|||||||
|
|
||||||
from oslo_log import log as oslo_logging
|
from oslo_log import log as oslo_logging
|
||||||
|
|
||||||
|
from cloudbaseinit.osutils import factory as osutils_factory
|
||||||
from cloudbaseinit.utils import network
|
from cloudbaseinit.utils import network
|
||||||
|
|
||||||
_DHCP_COOKIE = b'\x63\x82\x53\x63'
|
_DHCP_COOKIE = b'\x63\x82\x53\x63'
|
||||||
@ -96,14 +96,6 @@ def _parse_dhcp_reply(data, id_req):
|
|||||||
return True, options
|
return True, options
|
||||||
|
|
||||||
|
|
||||||
def _get_mac_address_by_local_ip(ip_addr):
|
|
||||||
for iface in netifaces.interfaces():
|
|
||||||
addrs = netifaces.ifaddresses(iface)
|
|
||||||
for addr in addrs.get(netifaces.AF_INET, []):
|
|
||||||
if addr['addr'] == ip_addr:
|
|
||||||
return addrs[netifaces.AF_LINK][0]['addr']
|
|
||||||
|
|
||||||
|
|
||||||
def _bind_dhcp_client_socket(s, max_bind_attempts, bind_retry_interval):
|
def _bind_dhcp_client_socket(s, max_bind_attempts, bind_retry_interval):
|
||||||
bind_attempts = 1
|
bind_attempts = 1
|
||||||
while True:
|
while True:
|
||||||
@ -138,7 +130,9 @@ def get_dhcp_options(dhcp_host=None, requested_options=[], timeout=5.0,
|
|||||||
s.settimeout(timeout)
|
s.settimeout(timeout)
|
||||||
|
|
||||||
local_ip_addr = network.get_local_ip(dhcp_host)
|
local_ip_addr = network.get_local_ip(dhcp_host)
|
||||||
mac_address = _get_mac_address_by_local_ip(local_ip_addr)
|
|
||||||
|
osutils = osutils_factory.get_os_utils()
|
||||||
|
mac_address = osutils.get_mac_address_by_local_ip(local_ip_addr)
|
||||||
|
|
||||||
data = _get_dhcp_request_data(id_req, mac_address, requested_options,
|
data = _get_dhcp_request_data(id_req, mac_address, requested_options,
|
||||||
vendor_id)
|
vendor_id)
|
||||||
|
@ -6,7 +6,6 @@ oslo.config
|
|||||||
oslo.log
|
oslo.log
|
||||||
Babel>=1.3
|
Babel>=1.3
|
||||||
oauthlib
|
oauthlib
|
||||||
netifaces
|
|
||||||
PyYAML
|
PyYAML
|
||||||
requests
|
requests
|
||||||
untangle==1.2.1
|
untangle==1.2.1
|
||||||
|
Loading…
x
Reference in New Issue
Block a user