Use MSFT_NetIPAddress in static network config
Change set_static_network_config in order to work with recent Windows versions as well. Partially-Implements: blueprint json-network-config Change-Id: Ie916d658265ca2895afcdebeaa5ae82d48b90082
This commit is contained in:
parent
518081b45b
commit
ac667f7f50
@ -84,8 +84,8 @@ class BaseOSUtils(object):
|
|||||||
def rename_network_adapter(self, old_name, new_name):
|
def rename_network_adapter(self, old_name, new_name):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def set_static_network_config(self, mac_address, address, netmask,
|
def set_static_network_config(self, name, address, prefix_len_or_netmask,
|
||||||
broadcast, gateway, dnsnameservers):
|
gateway, dnsnameservers):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def create_network_team(self, team_name, mode, load_balancing_algorithm,
|
def create_network_team(self, team_name, mode, load_balancing_algorithm,
|
||||||
|
@ -21,6 +21,7 @@ import struct
|
|||||||
import subprocess
|
import subprocess
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
import netaddr
|
||||||
from oslo_log import log as oslo_logging
|
from oslo_log import log as oslo_logging
|
||||||
import pywintypes
|
import pywintypes
|
||||||
import six
|
import six
|
||||||
@ -47,6 +48,8 @@ from cloudbaseinit.utils.windows import wmi_loader
|
|||||||
wmi = wmi_loader.wmi()
|
wmi = wmi_loader.wmi()
|
||||||
|
|
||||||
LOG = oslo_logging.getLogger(__name__)
|
LOG = oslo_logging.getLogger(__name__)
|
||||||
|
|
||||||
|
AF_INET = 2
|
||||||
AF_INET6 = 23
|
AF_INET6 = 23
|
||||||
UNICAST = 1
|
UNICAST = 1
|
||||||
MANUAL = 1
|
MANUAL = 1
|
||||||
@ -781,24 +784,30 @@ class WindowsUtils(base.BaseOSUtils):
|
|||||||
'Renaming interface "%(old_name)s" to "%(new_name)s" '
|
'Renaming interface "%(old_name)s" to "%(new_name)s" '
|
||||||
'failed' % {'old_name': old_name, 'new_name': new_name})
|
'failed' % {'old_name': old_name, 'new_name': new_name})
|
||||||
|
|
||||||
def set_static_network_config(self, mac_address, address, netmask,
|
@staticmethod
|
||||||
broadcast, gateway, dnsnameservers):
|
def _get_network_adapter(name):
|
||||||
conn = wmi.WMI(moniker='//./root/cimv2')
|
conn = wmi.WMI(moniker='//./root/cimv2')
|
||||||
|
query = conn.Win32_NetworkAdapter(NetConnectionID=name)
|
||||||
query = conn.query("SELECT * FROM Win32_NetworkAdapter WHERE "
|
|
||||||
"MACAddress = '{}'".format(mac_address))
|
|
||||||
if not len(query):
|
if not len(query):
|
||||||
raise exception.CloudbaseInitException(
|
raise exception.CloudbaseInitException(
|
||||||
"Network adapter not found")
|
"Network adapter not found: %s" % name)
|
||||||
|
return query[0]
|
||||||
|
|
||||||
adapter_config = query[0].associators(
|
@staticmethod
|
||||||
|
def _set_static_network_config_legacy(name, address, netmask, gateway,
|
||||||
|
dnsnameservers):
|
||||||
|
if netaddr.valid_ipv6(address):
|
||||||
|
LOG.warning("Setting IPv6 info not available on this system")
|
||||||
|
return
|
||||||
|
|
||||||
|
adapter_config = WindowsUtils._get_network_adapter(name).associators(
|
||||||
wmi_result_class='Win32_NetworkAdapterConfiguration')[0]
|
wmi_result_class='Win32_NetworkAdapterConfiguration')[0]
|
||||||
|
|
||||||
LOG.debug("Setting static IP address")
|
LOG.debug("Setting static IP address")
|
||||||
(ret_val,) = adapter_config.EnableStatic([address], [netmask])
|
(ret_val,) = adapter_config.EnableStatic([address], [netmask])
|
||||||
if ret_val > 1:
|
if ret_val > 1:
|
||||||
raise exception.CloudbaseInitException(
|
raise exception.CloudbaseInitException(
|
||||||
"Cannot set static IP address on network adapter (%d)",
|
"Cannot set static IP address on network adapter: %d" %
|
||||||
ret_val)
|
ret_val)
|
||||||
reboot_required = (ret_val == 1)
|
reboot_required = (ret_val == 1)
|
||||||
|
|
||||||
@ -807,8 +816,7 @@ class WindowsUtils(base.BaseOSUtils):
|
|||||||
(ret_val,) = adapter_config.SetGateways([gateway], [1])
|
(ret_val,) = adapter_config.SetGateways([gateway], [1])
|
||||||
if ret_val > 1:
|
if ret_val > 1:
|
||||||
raise exception.CloudbaseInitException(
|
raise exception.CloudbaseInitException(
|
||||||
"Cannot set gateway on network adapter (%d)",
|
"Cannot set gateway on network adapter: %d" % ret_val)
|
||||||
ret_val)
|
|
||||||
reboot_required = reboot_required or ret_val == 1
|
reboot_required = reboot_required or ret_val == 1
|
||||||
|
|
||||||
if dnsnameservers:
|
if dnsnameservers:
|
||||||
@ -816,62 +824,101 @@ class WindowsUtils(base.BaseOSUtils):
|
|||||||
(ret_val,) = adapter_config.SetDNSServerSearchOrder(dnsnameservers)
|
(ret_val,) = adapter_config.SetDNSServerSearchOrder(dnsnameservers)
|
||||||
if ret_val > 1:
|
if ret_val > 1:
|
||||||
raise exception.CloudbaseInitException(
|
raise exception.CloudbaseInitException(
|
||||||
"Cannot set DNS on network adapter (%d)",
|
"Cannot set DNS on network adapter: %d" % ret_val)
|
||||||
ret_val)
|
|
||||||
reboot_required = reboot_required or ret_val == 1
|
reboot_required = reboot_required or ret_val == 1
|
||||||
|
|
||||||
return reboot_required
|
return reboot_required
|
||||||
|
|
||||||
def set_static_network_config_v6(self, mac_address, address6,
|
@staticmethod
|
||||||
netmask6, gateway6):
|
def _fix_network_adapter_dhcp(interface_name, enable_dhcp, address_family):
|
||||||
"""Set IPv6 info for a network card."""
|
interface_id = WindowsUtils._get_network_adapter(interface_name).GUID
|
||||||
|
tcpip_key = "Tcpip6" if address_family == AF_INET6 else "Tcpip"
|
||||||
|
|
||||||
# Get local properties by MAC identification.
|
with winreg.OpenKey(
|
||||||
adapters = network.get_adapter_addresses()
|
winreg.HKEY_LOCAL_MACHINE,
|
||||||
for adapter in adapters:
|
"SYSTEM\\CurrentControlSet\\services\\%(tcpip_key)s\\"
|
||||||
if mac_address == adapter["mac_address"]:
|
"Parameters\\Interfaces\\%(interface_id)s" %
|
||||||
ifname = adapter["friendly_name"]
|
{"tcpip_key": tcpip_key, "interface_id": interface_id},
|
||||||
ifindex = adapter["interface_index"]
|
0, winreg.KEY_SET_VALUE) as key:
|
||||||
break
|
winreg.SetValueEx(
|
||||||
|
key, 'EnableDHCP', 0, winreg.REG_DWORD,
|
||||||
|
1 if enable_dhcp else 0)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _set_interface_dns(interface_name, dnsnameservers):
|
||||||
|
# Import here to avoid loading errors on Windows versions where MI is
|
||||||
|
# not available
|
||||||
|
import mi
|
||||||
|
|
||||||
|
conn = wmi.WMI(moniker='//./root/standardcimv2')
|
||||||
|
# Requires Windows >= 6.2
|
||||||
|
dns_client = conn.MSFT_DnsClientServerAddress(
|
||||||
|
InterfaceAlias=interface_name)
|
||||||
|
if not len(dns_client):
|
||||||
|
raise exception.ItemNotFoundException(
|
||||||
|
'Network interface with name "%s" not found' %
|
||||||
|
interface_name)
|
||||||
|
dns_client = dns_client[0]
|
||||||
|
|
||||||
|
custom_options = [{
|
||||||
|
u'name': u'ServerAddresses',
|
||||||
|
u'value_type': mi.MI_ARRAY | mi.MI_STRING,
|
||||||
|
u'value': dnsnameservers
|
||||||
|
}]
|
||||||
|
|
||||||
|
operation_options = {u'custom_options': custom_options}
|
||||||
|
dns_client.put(operation_options=operation_options)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _set_static_network_config(name, address, prefix_len, gateway):
|
||||||
|
if netaddr.valid_ipv6(address):
|
||||||
|
family = AF_INET6
|
||||||
else:
|
else:
|
||||||
raise exception.CloudbaseInitException(
|
family = AF_INET
|
||||||
"Adapter with MAC {!r} not available".format(mac_address))
|
|
||||||
|
|
||||||
# TODO(cpoieana): Extend support for other platforms.
|
# This is needed to avoid the error:
|
||||||
# Currently windows8 @ ws2012 or above.
|
# "Inconsistent parameters PolicyStore PersistentStore and
|
||||||
if not self.check_os_version(6, 2):
|
# Dhcp Enabled"
|
||||||
LOG.warning("Setting IPv6 info not available "
|
WindowsUtils._fix_network_adapter_dhcp(name, False, family)
|
||||||
"on this system")
|
|
||||||
return
|
|
||||||
conn = wmi.WMI(moniker='//./root/StandardCimv2')
|
|
||||||
query = conn.query("SELECT * FROM MSFT_NetIPAddress "
|
|
||||||
"WHERE InterfaceAlias = '{}'".format(ifname))
|
|
||||||
netip = query[0]
|
|
||||||
|
|
||||||
params = {
|
conn = wmi.WMI(moniker='//./root/standardcimv2')
|
||||||
"InterfaceIndex": ifindex,
|
existing_addresses = conn.MSFT_NetIPAddress(
|
||||||
"InterfaceAlias": ifname,
|
AddressFamily=family, InterfaceAlias=name)
|
||||||
"IPAddress": address6,
|
for existing_address in existing_addresses:
|
||||||
"AddressFamily": AF_INET6,
|
LOG.debug(
|
||||||
"PrefixLength": netmask6,
|
"Removing existing IP address \"%(ip)s\" "
|
||||||
# Manual set type.
|
"from adapter \"%(name)s\"",
|
||||||
"Type": UNICAST,
|
{"ip": existing_address.IPAddress, "name": name})
|
||||||
"PrefixOrigin": MANUAL,
|
existing_address.Delete_()
|
||||||
"SuffixOrigin": MANUAL,
|
|
||||||
"AddressState": PREFERRED_ADDR,
|
existing_routes = conn.MSFT_NetRoute(
|
||||||
# No expiry.
|
AddressFamily=family, InterfaceAlias=name)
|
||||||
"ValidLifetime": None,
|
for existing_route in existing_routes:
|
||||||
"PreferredLifetime": None,
|
LOG.debug(
|
||||||
"SkipAsSource": False,
|
"Removing existing route \"%(route)s\" "
|
||||||
"DefaultGateway": gateway6,
|
"from adapter \"%(name)s\"",
|
||||||
"PolicyStore": None,
|
{"route": existing_route.DestinationPrefix, "name": name})
|
||||||
"PassThru": False,
|
existing_route.Delete_()
|
||||||
}
|
|
||||||
LOG.debug("Setting IPv6 info for %s", ifname)
|
conn.MSFT_NetIPAddress.create(
|
||||||
try:
|
AddressFamily=family, InterfaceAlias=name, IPAddress=address,
|
||||||
netip.Create(**params)
|
PrefixLength=prefix_len, DefaultGateway=gateway)
|
||||||
except wmi.x_wmi as exc:
|
|
||||||
raise exception.CloudbaseInitException(exc.com_error)
|
def set_static_network_config(self, name, address, prefix_len_or_netmask,
|
||||||
|
gateway, dnsnameservers):
|
||||||
|
ip_network = netaddr.IPNetwork(
|
||||||
|
u"%s/%s" % (address, prefix_len_or_netmask))
|
||||||
|
prefix_len = ip_network.prefixlen
|
||||||
|
netmask = str(ip_network.netmask)
|
||||||
|
|
||||||
|
if self.check_os_version(6, 2):
|
||||||
|
self._set_static_network_config(
|
||||||
|
name, address, prefix_len, gateway)
|
||||||
|
if len(dnsnameservers):
|
||||||
|
self._set_interface_dns(name, dnsnameservers)
|
||||||
|
else:
|
||||||
|
return self._set_static_network_config_legacy(
|
||||||
|
name, address, netmask, gateway, dnsnameservers)
|
||||||
|
|
||||||
def _get_network_team_manager(self):
|
def _get_network_team_manager(self):
|
||||||
if self._network_team_manager:
|
if self._network_team_manager:
|
||||||
|
@ -145,24 +145,27 @@ class NetworkConfigPlugin(plugin_base.BasePlugin):
|
|||||||
if not nic:
|
if not nic:
|
||||||
LOG.warn("Missing details for adapter %s", mac)
|
LOG.warn("Missing details for adapter %s", mac)
|
||||||
continue
|
continue
|
||||||
LOG.info("Configuring network adapter %s", mac)
|
|
||||||
|
name = osutils.get_network_adapter_name_by_mac_address(mac)
|
||||||
|
LOG.info("Configuring network adapter: %s", name)
|
||||||
reboot = osutils.set_static_network_config(
|
reboot = osutils.set_static_network_config(
|
||||||
mac,
|
name,
|
||||||
nic.address,
|
nic.address,
|
||||||
nic.netmask,
|
nic.netmask,
|
||||||
nic.broadcast,
|
|
||||||
nic.gateway,
|
nic.gateway,
|
||||||
nic.dnsnameservers
|
nic.dnsnameservers
|
||||||
)
|
)
|
||||||
reboot_required = reboot or reboot_required
|
reboot_required = reboot or reboot_required
|
||||||
# Set v6 info too if available.
|
# Set v6 info too if available.
|
||||||
if nic.address6 and nic.netmask6:
|
if nic.address6 and nic.netmask6:
|
||||||
osutils.set_static_network_config_v6(
|
reboot = osutils.set_static_network_config(
|
||||||
mac,
|
name,
|
||||||
nic.address6,
|
nic.address6,
|
||||||
nic.netmask6,
|
nic.netmask6,
|
||||||
nic.gateway6
|
nic.gateway6,
|
||||||
|
[]
|
||||||
)
|
)
|
||||||
|
reboot_required = reboot or reboot_required
|
||||||
configured = True
|
configured = True
|
||||||
for mac in macnics:
|
for mac in macnics:
|
||||||
LOG.warn("Details not used for adapter %s", mac)
|
LOG.warn("Details not used for adapter %s", mac)
|
||||||
|
@ -18,6 +18,8 @@ import functools
|
|||||||
import importlib
|
import importlib
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
import netaddr
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import unittest.mock as mock
|
import unittest.mock as mock
|
||||||
except ImportError:
|
except ImportError:
|
||||||
@ -588,18 +590,96 @@ class TestWindowsUtils(testutils.CloudbaseInitTestBase):
|
|||||||
def test_get_network_adapters_xp_2003(self):
|
def test_get_network_adapters_xp_2003(self):
|
||||||
self._test_get_network_adapters(True)
|
self._test_get_network_adapters(True)
|
||||||
|
|
||||||
def _test_set_static_network_config(self, adapter=True, static_val=(0,),
|
@mock.patch('cloudbaseinit.osutils.windows.WindowsUtils'
|
||||||
gateway_val=(0,), dns_val=(0,)):
|
'.check_os_version')
|
||||||
conn = self._wmi_mock.WMI
|
def _test_set_static_network_config(self, mock_check_os_version,
|
||||||
mac_address = '54:EE:75:19:F4:61'
|
adapter=True, static_val=(0,),
|
||||||
|
gateway_val=(0,), dns_val=(0,),
|
||||||
|
legacy=False, ipv6=False):
|
||||||
|
mock_check_os_version.return_value = not legacy
|
||||||
|
if legacy:
|
||||||
|
self._test_set_static_network_config_legacy(
|
||||||
|
adapter, static_val, gateway_val, dns_val)
|
||||||
|
else:
|
||||||
|
self._test_set_static_network_config_new(ipv6=ipv6)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.osutils.windows.WindowsUtils'
|
||||||
|
'._fix_network_adapter_dhcp')
|
||||||
|
def _test_set_static_network_config_new(self,
|
||||||
|
mock_fix_network_adapter_dhcp,
|
||||||
|
ipv6):
|
||||||
|
conn = self._wmi_mock.WMI.return_value
|
||||||
|
if ipv6:
|
||||||
|
mock.sentinel.address = "2001:db8::3"
|
||||||
|
mock.sentinel.prefix_len_or_netmask = 64
|
||||||
|
else:
|
||||||
|
mock.sentinel.address = "10.10.10.10"
|
||||||
|
mock.sentinel.prefix_len_or_netmask = "255.255.255.0"
|
||||||
|
|
||||||
|
adapter = mock.Mock()
|
||||||
|
adapter.GUID = mock.sentinel.adapter_guid
|
||||||
|
conn.Win32_NetworkAdapter.return_value = [adapter]
|
||||||
|
|
||||||
|
if netaddr.valid_ipv6(mock.sentinel.address):
|
||||||
|
family = self.windows_utils.AF_INET6
|
||||||
|
else:
|
||||||
|
family = self.windows_utils.AF_INET
|
||||||
|
|
||||||
|
existing_adapter = mock.Mock()
|
||||||
|
existing_adapter.IPAddress = mock.sentinel.address
|
||||||
|
conn.MSFT_NetIPAddress.return_value = [existing_adapter]
|
||||||
|
|
||||||
|
existing_route = mock.Mock()
|
||||||
|
existing_route.DestinationPrefix = "0.0.0.0"
|
||||||
|
conn.MSFT_NetRoute.return_value = [existing_route]
|
||||||
|
|
||||||
|
dns_client = mock.Mock()
|
||||||
|
conn.MSFT_DnsClientServerAddress.return_value = [dns_client]
|
||||||
|
|
||||||
|
self._winutils.set_static_network_config(
|
||||||
|
mock.sentinel.nick_name, mock.sentinel.address,
|
||||||
|
mock.sentinel.prefix_len_or_netmask, mock.sentinel.gateway,
|
||||||
|
[mock.sentinel.dns])
|
||||||
|
|
||||||
|
mock_fix_network_adapter_dhcp.assert_called_once_with(
|
||||||
|
mock.sentinel.nick_name, False, family)
|
||||||
|
|
||||||
|
conn.MSFT_NetIPAddress.assert_called_once_with(
|
||||||
|
AddressFamily=family, InterfaceAlias=mock.sentinel.nick_name)
|
||||||
|
existing_adapter.Delete_.assert_called_once_with()
|
||||||
|
|
||||||
|
conn.MSFT_NetRoute.assert_called_once_with(
|
||||||
|
AddressFamily=family, InterfaceAlias=mock.sentinel.nick_name)
|
||||||
|
existing_route.Delete_.assert_called_once_with()
|
||||||
|
|
||||||
|
ip_network = netaddr.IPNetwork(
|
||||||
|
u"%s/%s" % (
|
||||||
|
mock.sentinel.address, mock.sentinel.prefix_len_or_netmask))
|
||||||
|
prefix_len = ip_network.prefixlen
|
||||||
|
|
||||||
|
conn.MSFT_NetIPAddress.create.assert_called_once_with(
|
||||||
|
AddressFamily=family, InterfaceAlias=mock.sentinel.nick_name,
|
||||||
|
IPAddress=mock.sentinel.address, PrefixLength=prefix_len,
|
||||||
|
DefaultGateway=mock.sentinel.gateway)
|
||||||
|
|
||||||
|
custom_options = [{
|
||||||
|
u'name': u'ServerAddresses',
|
||||||
|
u'value_type': self._mi_mock.MI_ARRAY | self._mi_mock.MI_STRING,
|
||||||
|
u'value': [mock.sentinel.dns]
|
||||||
|
}]
|
||||||
|
operation_options = {u'custom_options': custom_options}
|
||||||
|
dns_client.put.assert_called_once_with(
|
||||||
|
operation_options=operation_options)
|
||||||
|
|
||||||
|
def _test_set_static_network_config_legacy(self, adapter, static_val,
|
||||||
|
gateway_val, dns_val):
|
||||||
|
conn = self._wmi_mock.WMI.return_value
|
||||||
|
nic_name = 'fake NIC'
|
||||||
address = '10.10.10.10'
|
address = '10.10.10.10'
|
||||||
broadcast = '0.0.0.0'
|
|
||||||
dns_list = ['8.8.8.8']
|
dns_list = ['8.8.8.8']
|
||||||
set_static_call = functools.partial(
|
set_static_call = functools.partial(
|
||||||
self._winutils.set_static_network_config,
|
self._winutils.set_static_network_config,
|
||||||
mac_address, address, self._NETMASK,
|
nic_name, address, self._NETMASK, self._GATEWAY, dns_list)
|
||||||
broadcast, self._GATEWAY, dns_list
|
|
||||||
)
|
|
||||||
|
|
||||||
if adapter:
|
if adapter:
|
||||||
adapter = mock.MagicMock()
|
adapter = mock.MagicMock()
|
||||||
@ -617,8 +697,8 @@ class TestWindowsUtils(testutils.CloudbaseInitTestBase):
|
|||||||
if ret_val in (0, 1):
|
if ret_val in (0, 1):
|
||||||
expected_log.append(msg)
|
expected_log.append(msg)
|
||||||
|
|
||||||
conn.return_value.query.return_value = adapter
|
conn.Win32_NetworkAdapter.return_value = [adapter]
|
||||||
adapter_config = adapter[0].associators.return_value[0]
|
adapter_config = adapter.associators.return_value[0]
|
||||||
adapter_config.EnableStatic.return_value = static_val
|
adapter_config.EnableStatic.return_value = static_val
|
||||||
adapter_config.SetGateways.return_value = gateway_val
|
adapter_config.SetGateways.return_value = gateway_val
|
||||||
adapter_config.SetDNSServerSearchOrder.return_value = dns_val
|
adapter_config.SetDNSServerSearchOrder.return_value = dns_val
|
||||||
@ -636,10 +716,9 @@ class TestWindowsUtils(testutils.CloudbaseInitTestBase):
|
|||||||
self.assertFalse(response)
|
self.assertFalse(response)
|
||||||
self.assertEqual(expected_log, self.snatcher.output)
|
self.assertEqual(expected_log, self.snatcher.output)
|
||||||
|
|
||||||
select = ("SELECT * FROM Win32_NetworkAdapter WHERE "
|
conn.Win32_NetworkAdapter.assert_called_once_with(
|
||||||
"MACAddress = '{}'".format(mac_address))
|
NetConnectionID=nic_name)
|
||||||
conn.return_value.query.assert_called_once_with(select)
|
adapter.associators.assert_called_with(
|
||||||
adapter[0].associators.assert_called_with(
|
|
||||||
wmi_result_class='Win32_NetworkAdapterConfiguration')
|
wmi_result_class='Win32_NetworkAdapterConfiguration')
|
||||||
adapter_config.EnableStatic.assert_called_with(
|
adapter_config.EnableStatic.assert_called_with(
|
||||||
[address], [self._NETMASK])
|
[address], [self._NETMASK])
|
||||||
@ -648,123 +727,52 @@ class TestWindowsUtils(testutils.CloudbaseInitTestBase):
|
|||||||
adapter_config.SetDNSServerSearchOrder.assert_called_with(
|
adapter_config.SetDNSServerSearchOrder.assert_called_with(
|
||||||
dns_list)
|
dns_list)
|
||||||
|
|
||||||
@mock.patch('cloudbaseinit.osutils.windows.WindowsUtils'
|
def test_set_static_network_config_legacy(self):
|
||||||
'.check_os_version')
|
|
||||||
@mock.patch("cloudbaseinit.utils.windows.network"
|
|
||||||
".get_adapter_addresses")
|
|
||||||
def _test_set_static_network_config_v6(self, mock_get_adapter_addresses,
|
|
||||||
mock_check_os_version,
|
|
||||||
v6adapters=True, v6error=False):
|
|
||||||
friendly_name = "Ethernet0"
|
|
||||||
interface_index = "4"
|
|
||||||
mac_address = '54:EE:75:19:F4:61'
|
|
||||||
address6 = "2001:db8::3"
|
|
||||||
netmask6 = "64"
|
|
||||||
gateway6 = "2001:db8::1"
|
|
||||||
|
|
||||||
conn = self._wmi_mock.WMI
|
|
||||||
netip = conn.return_value.query.return_value[0]
|
|
||||||
if v6error:
|
|
||||||
netip.Create.side_effect = WMIError
|
|
||||||
adapter_addresses = []
|
|
||||||
if v6adapters:
|
|
||||||
adapter_addresses = [
|
|
||||||
{
|
|
||||||
"mac_address": mac_address,
|
|
||||||
"friendly_name": friendly_name,
|
|
||||||
"interface_index": interface_index
|
|
||||||
}
|
|
||||||
]
|
|
||||||
mock_get_adapter_addresses.return_value = adapter_addresses
|
|
||||||
mock_check_os_version.return_value = True
|
|
||||||
|
|
||||||
set_static_call = functools.partial(
|
|
||||||
self._winutils.set_static_network_config_v6,
|
|
||||||
mac_address, address6, netmask6, gateway6)
|
|
||||||
expected_log = []
|
|
||||||
if not mock_check_os_version.return_value:
|
|
||||||
expected_log.append("Setting IPv6 info not available "
|
|
||||||
"on this system")
|
|
||||||
|
|
||||||
if not v6adapters or v6error:
|
|
||||||
self.assertRaises(
|
|
||||||
exception.CloudbaseInitException,
|
|
||||||
set_static_call)
|
|
||||||
else:
|
|
||||||
expected_log.append("Setting IPv6 info for %s" % friendly_name)
|
|
||||||
with self.snatcher:
|
|
||||||
set_static_call()
|
|
||||||
mock_get_adapter_addresses.assert_called_once_with()
|
|
||||||
select = ("SELECT * FROM MSFT_NetIPAddress "
|
|
||||||
"WHERE InterfaceAlias = '{}'".format(friendly_name))
|
|
||||||
conn.return_value.query.assert_called_once_with(select)
|
|
||||||
params = {
|
|
||||||
"InterfaceIndex": interface_index,
|
|
||||||
"InterfaceAlias": friendly_name,
|
|
||||||
"IPAddress": address6,
|
|
||||||
"AddressFamily": self.windows_utils.AF_INET6,
|
|
||||||
"PrefixLength": netmask6,
|
|
||||||
# Manual set type.
|
|
||||||
"Type": self.windows_utils.UNICAST,
|
|
||||||
"PrefixOrigin": self.windows_utils.MANUAL,
|
|
||||||
"SuffixOrigin": self.windows_utils.MANUAL,
|
|
||||||
"AddressState": self.windows_utils.PREFERRED_ADDR,
|
|
||||||
# No expiry.
|
|
||||||
"ValidLifetime": None,
|
|
||||||
"PreferredLifetime": None,
|
|
||||||
"SkipAsSource": False,
|
|
||||||
"DefaultGateway": gateway6,
|
|
||||||
"PolicyStore": None,
|
|
||||||
"PassThru": False,
|
|
||||||
}
|
|
||||||
netip.Create.assert_called_once_with(**params)
|
|
||||||
self.assertEqual(expected_log, self.snatcher.output)
|
|
||||||
|
|
||||||
def test_set_static_network_config(self):
|
|
||||||
ret_val1 = (1,)
|
ret_val1 = (1,)
|
||||||
ret_val2 = (1,)
|
ret_val2 = (1,)
|
||||||
ret_val3 = (0,)
|
ret_val3 = (0,)
|
||||||
self._test_set_static_network_config(static_val=ret_val1,
|
self._test_set_static_network_config(static_val=ret_val1,
|
||||||
gateway_val=ret_val2,
|
gateway_val=ret_val2,
|
||||||
dns_val=ret_val3)
|
dns_val=ret_val3,
|
||||||
|
legacy=True)
|
||||||
|
|
||||||
def test_set_static_network_config_query_fail(self):
|
def test_set_static_network_config_legacy_query_fail(self):
|
||||||
self._test_set_static_network_config(adapter=False)
|
self._test_set_static_network_config(adapter=False, legacy=True)
|
||||||
|
|
||||||
def test_set_static_network_config_cannot_set_ip(self):
|
def test_set_static_network_config_legacy_cannot_set_ip(self):
|
||||||
ret_val1 = (2,)
|
ret_val1 = (2,)
|
||||||
self._test_set_static_network_config(static_val=ret_val1)
|
self._test_set_static_network_config(static_val=ret_val1, legacy=True)
|
||||||
|
|
||||||
def test_set_static_network_config_cannot_set_gateway(self):
|
def test_set_static_network_config_legacy_cannot_set_gateway(self):
|
||||||
ret_val1 = (1,)
|
ret_val1 = (1,)
|
||||||
ret_val2 = (2,)
|
ret_val2 = (2,)
|
||||||
self._test_set_static_network_config(static_val=ret_val1,
|
self._test_set_static_network_config(static_val=ret_val1,
|
||||||
gateway_val=ret_val2)
|
gateway_val=ret_val2,
|
||||||
|
legacy=True)
|
||||||
|
|
||||||
def test_set_static_network_config_cannot_set_DNS(self):
|
def test_set_static_network_config_legacy_cannot_set_DNS(self):
|
||||||
ret_val1 = (1,)
|
ret_val1 = (1,)
|
||||||
ret_val2 = (1,)
|
ret_val2 = (1,)
|
||||||
ret_val3 = (2,)
|
ret_val3 = (2,)
|
||||||
self._test_set_static_network_config(static_val=ret_val1,
|
self._test_set_static_network_config(static_val=ret_val1,
|
||||||
gateway_val=ret_val2,
|
gateway_val=ret_val2,
|
||||||
dns_val=ret_val3)
|
dns_val=ret_val3,
|
||||||
|
legacy=True)
|
||||||
|
|
||||||
def test_set_static_network_config_no_reboot(self):
|
def test_set_static_network_config_legacy_no_reboot(self):
|
||||||
ret_val1 = (0,)
|
ret_val1 = (0,)
|
||||||
ret_val2 = (0,)
|
ret_val2 = (0,)
|
||||||
ret_val3 = (0,)
|
ret_val3 = (0,)
|
||||||
self._test_set_static_network_config(static_val=ret_val1,
|
self._test_set_static_network_config(static_val=ret_val1,
|
||||||
gateway_val=ret_val2,
|
gateway_val=ret_val2,
|
||||||
dns_val=ret_val3)
|
dns_val=ret_val3,
|
||||||
|
legacy=True)
|
||||||
|
|
||||||
def test_set_static_network_config_v6(self):
|
def test_set_static_network_config_ipv4(self):
|
||||||
self._test_set_static_network_config_v6()
|
self._test_set_static_network_config(ipv6=False)
|
||||||
|
|
||||||
def test_set_static_network_config_v6_no_adapters(self):
|
def test_set_static_network_config_ipv6(self):
|
||||||
self._test_set_static_network_config_v6(v6adapters=False)
|
self._test_set_static_network_config(ipv6=True)
|
||||||
|
|
||||||
def test_set_static_network_config_v6_error(self):
|
|
||||||
self._test_set_static_network_config_v6(v6error=True)
|
|
||||||
|
|
||||||
@mock.patch('cloudbaseinit.osutils.windows.WindowsUtils'
|
@mock.patch('cloudbaseinit.osutils.windows.WindowsUtils'
|
||||||
'.execute_process')
|
'.execute_process')
|
||||||
|
@ -48,6 +48,10 @@ class TestNetworkConfigPlugin(unittest.TestCase):
|
|||||||
mock_get_os_utils.return_value = mock_osutils
|
mock_get_os_utils.return_value = mock_osutils
|
||||||
mock_osutils.get_network_adapters.return_value = network_adapters
|
mock_osutils.get_network_adapters.return_value = network_adapters
|
||||||
mock_osutils.set_static_network_config.return_value = True
|
mock_osutils.set_static_network_config.return_value = True
|
||||||
|
|
||||||
|
mock_osutils.get_network_adapter_name_by_mac_address = (
|
||||||
|
lambda mac: [n[0] for n in network_adapters if n[1] == mac][0])
|
||||||
|
|
||||||
network_execute = functools.partial(
|
network_execute = functools.partial(
|
||||||
self._network_plugin.execute,
|
self._network_plugin.execute,
|
||||||
mock_service, mock_shared_data
|
mock_service, mock_shared_data
|
||||||
@ -66,7 +70,7 @@ class TestNetworkConfigPlugin(unittest.TestCase):
|
|||||||
'common.networkconfig'):
|
'common.networkconfig'):
|
||||||
ret = network_execute()
|
ret = network_execute()
|
||||||
|
|
||||||
calls, calls6 = [], []
|
calls = []
|
||||||
for adapter in set(network_adapters) - set(missed_adapters):
|
for adapter in set(network_adapters) - set(missed_adapters):
|
||||||
nics = [nic for nic in (network_details +
|
nics = [nic for nic in (network_details +
|
||||||
extra_network_details)
|
extra_network_details)
|
||||||
@ -74,32 +78,27 @@ class TestNetworkConfigPlugin(unittest.TestCase):
|
|||||||
self.assertTrue(nics) # missed_adapters should do the job
|
self.assertTrue(nics) # missed_adapters should do the job
|
||||||
nic = nics[0]
|
nic = nics[0]
|
||||||
call = mock.call(
|
call = mock.call(
|
||||||
nic.mac,
|
adapter[0],
|
||||||
nic.address,
|
nic.address,
|
||||||
nic.netmask,
|
nic.netmask,
|
||||||
nic.broadcast,
|
|
||||||
nic.gateway,
|
nic.gateway,
|
||||||
nic.dnsnameservers
|
nic.dnsnameservers
|
||||||
)
|
)
|
||||||
call6 = mock.call(
|
call6 = mock.call(
|
||||||
nic.mac,
|
adapter[0],
|
||||||
nic.address6,
|
nic.address6,
|
||||||
nic.netmask6,
|
nic.netmask6,
|
||||||
nic.gateway6
|
nic.gateway6,
|
||||||
|
[]
|
||||||
)
|
)
|
||||||
calls.append(call)
|
calls.append(call)
|
||||||
if nic.address6 and nic.netmask6:
|
if nic.address6 and nic.netmask6:
|
||||||
calls6.append(call6)
|
calls.append(call6)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
len(calls),
|
len(calls),
|
||||||
mock_osutils.set_static_network_config.call_count)
|
mock_osutils.set_static_network_config.call_count)
|
||||||
self.assertEqual(
|
|
||||||
len(calls6),
|
|
||||||
mock_osutils.set_static_network_config_v6.call_count)
|
|
||||||
mock_osutils.set_static_network_config.assert_has_calls(
|
mock_osutils.set_static_network_config.assert_has_calls(
|
||||||
calls, any_order=True)
|
calls, any_order=True)
|
||||||
mock_osutils.set_static_network_config_v6.assert_has_calls(
|
|
||||||
calls6, any_order=True)
|
|
||||||
reboot = len(missed_adapters) != self._count
|
reboot = len(missed_adapters) != self._count
|
||||||
self.assertEqual((plugin_base.PLUGIN_EXECUTION_DONE, reboot), ret)
|
self.assertEqual((plugin_base.PLUGIN_EXECUTION_DONE, reboot), ret)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user