# Copyright (c) 2017-2024 Wind River Systems, Inc. # # SPDX-License-Identifier: Apache-2.0 # from __future__ import print_function import os import uuid import yaml import mock import netaddr import json from sysinv.common import utils from sysinv.common import constants from sysinv.puppet import interface from sysinv.puppet import puppet from sysinv.objects import base as objbase from sysinv.tests.db import base as dbbase from sysinv.tests.db import utils as dbutils from sysinv.tests.puppet import base from sysinv.db import api as db_api from collections import defaultdict NETWORKTYPES_WITH_V4_ADDRESSES = [constants.NETWORK_TYPE_MGMT, constants.NETWORK_TYPE_OAM, constants.NETWORK_TYPE_CLUSTER_HOST, constants.NETWORK_TYPE_PXEBOOT] NETWORKTYPES_WITH_V6_ADDRESSES = [constants.NETWORK_TYPE_DATA] NETWORKTYPES_WITH_V4_ROUTES = [constants.NETWORK_TYPE_DATA] NETWORKTYPES_WITH_V6_ROUTES = [constants.NETWORK_TYPE_DATA] class InterfaceTestCaseMixin(base.PuppetTestCaseMixin): """ This InterfaceTestCaseMixin needs to be used with a subclass of BaseHostTestCase """ def assertIn(self, needle, haystack, message=''): """Custom assertIn that handles object comparison""" if isinstance(needle, objbase.SysinvObject): # compare objects based on unique DB identifier needle = needle.id haystack = [o.id for o in haystack] super(InterfaceTestCaseMixin, self).assertIn(needle, haystack, message) def assertEqual(self, expected, observed, message=''): """Custom assertEqual that handles object comparison""" if (isinstance(expected, objbase.SysinvObject) and isinstance(observed, objbase.SysinvObject)): expected = expected.id observed = observed.id super(InterfaceTestCaseMixin, self).assertEqual(expected, observed, message) def _get_network_type_list(self, networktype): if isinstance(networktype, list): networktypelist = networktype elif networktype: networktypelist = [networktype] else: networktypelist = [] return networktypelist def _get_network_ids_by_type(self, networktype): networktypelist = self._get_network_type_list(networktype) networks = [] for network_type in networktypelist: network = self._find_network_by_type(network_type) if network: networks.append(str(network['id'])) return networks def _create_ethernet_test(self, ifname=None, ifclass=None, networktype=None, hostname=None, **kwargs): interface_id = len(self.interfaces) if not ifname: ifname = (networktype or 'eth') + str(interface_id) if not ifclass: ifclass = constants.INTERFACE_CLASS_NONE if ifclass == constants.INTERFACE_CLASS_PLATFORM: networks = self._get_network_ids_by_type(networktype) else: networks = [] interface = {'id': interface_id, 'uuid': str(uuid.uuid4()), 'forihostid': self.host.id, 'ifname': ifname, 'iftype': constants.INTERFACE_TYPE_ETHERNET, 'imac': '02:11:22:33:44:' + str(10 + interface_id), 'uses': [], 'used_by': [], 'ifclass': ifclass, 'networks': networks, 'networktype': networktype, 'imtu': 1500, 'sriov_numvfs': kwargs.get('sriov_numvfs', 0), 'sriov_vf_driver': kwargs.get('iface_sriov_vf_driver', None), 'max_tx_rate': kwargs.get('max_tx_rate', None), 'ipv4_mode': kwargs.get('ipv4_mode', None), 'ipv6_mode': kwargs.get('ipv6_mode', None)} db_interface = dbutils.create_test_interface(**interface) for network in networks: dbutils.create_test_interface_network_assign(db_interface['id'], network) self.interfaces.append(db_interface) port_id = len(self.ports) port = {'id': port_id, 'uuid': str(uuid.uuid4()), 'name': 'eth' + str(port_id), 'interface_id': interface_id, 'host_id': self.host.id, 'mac': interface['imac'], 'driver': kwargs.get('driver', 'ixgbe'), 'dpdksupport': kwargs.get('dpdksupport', True), 'pdevice': kwargs.get('pdevice', "Ethernet Controller X710 for 10GbE SFP+ [1572]"), 'pciaddr': kwargs.get('pciaddr', '0000:00:00.' + str(port_id + 1)), 'dev_id': kwargs.get('dev_id', 0), 'sriov_vf_driver': kwargs.get('port_sriov_vf_driver', None), 'sriov_vf_pdevice_id': kwargs.get('sriov_vf_pdevice_id', None), 'sriov_vfs_pci_address': kwargs.get('sriov_vfs_pci_address', '')} db_port = dbutils.create_test_ethernet_port(**port) self.ports.append(db_port) if hostname: self._assign_addresses_to_interface(hostname, db_interface, networktype) db_interface.networktypelist = self._get_network_type_list(networktype) return db_port, db_interface def _create_vlan_test(self, ifname, ifclass, networktype, vlan_id, lower_iface=None, hostname=None, **kwargs): if not lower_iface: lower_port, lower_iface = self._create_ethernet_test() if not ifname: ifname = 'vlan' + str(vlan_id) if not ifclass: ifclass = constants.INTERFACE_CLASS_NONE if ifclass == constants.INTERFACE_CLASS_PLATFORM: networks = self._get_network_ids_by_type(networktype) else: networks = [] interface_id = len(self.interfaces) interface = {'id': interface_id, 'uuid': str(uuid.uuid4()), 'forihostid': self.host.id, 'ifname': ifname, 'iftype': constants.INTERFACE_TYPE_VLAN, 'vlan_id': vlan_id, 'imac': '02:11:22:33:44:' + str(10 + interface_id), 'uses': [lower_iface['ifname']], 'used_by': [], 'ifclass': ifclass, 'networks': networks, 'networktype': networktype, 'imtu': 1500, 'ipv4_mode': kwargs.get('ipv4_mode', None), 'ipv6_mode': kwargs.get('ipv6_mode', None)} lower_iface['used_by'].append(interface['ifname']) db_interface = dbutils.create_test_interface(**interface) for network in networks: dbutils.create_test_interface_network_assign(db_interface['id'], network) self.interfaces.append(db_interface) if hostname: self._assign_addresses_to_interface(hostname, db_interface, networktype) db_interface.networktypelist = self._get_network_type_list(networktype) return db_interface def _create_bond_test(self, ifname, ifclass=None, networktype=None, hostname=None, **kwargs): iface1 = kwargs.get('iface1', None) if not iface1: port1, iface1 = self._create_ethernet_test() iface2 = kwargs.get('iface2', None) if not iface2: port2, iface2 = self._create_ethernet_test() interface_id = len(self.interfaces) if not ifname: ifname = 'bond' + str(interface_id) if not ifclass: ifclass = constants.INTERFACE_CLASS_NONE if ifclass == constants.INTERFACE_CLASS_PLATFORM: networks = self._get_network_ids_by_type(networktype) else: networks = [] interface = {'id': interface_id, 'uuid': str(uuid.uuid4()), 'forihostid': self.host.id, 'ifname': ifname, 'iftype': constants.INTERFACE_TYPE_AE, 'imac': '02:11:22:33:44:' + str(10 + interface_id), 'uses': [iface1['ifname'], iface2['ifname']], 'used_by': [], 'ifclass': ifclass, 'networks': networks, 'networktype': networktype, 'imtu': 1500, 'txhashpolicy': 'layer2', 'primary_reselect': kwargs.get('primary_reselect', None), 'ipv4_mode': kwargs.get('ipv4_mode', None), 'ipv6_mode': kwargs.get('ipv6_mode', None)} aemode = kwargs.get('aemode', None) if aemode: interface['aemode'] = aemode else: lacp_types = [constants.NETWORK_TYPE_MGMT, constants.NETWORK_TYPE_PXEBOOT] if networktype in lacp_types: interface['aemode'] = '802.3ad' else: interface['aemode'] = 'balanced' iface1['used_by'].append(interface['ifname']) iface2['used_by'].append(interface['ifname']) db_interface = dbutils.create_test_interface(**interface) for network in networks: dbutils.create_test_interface_network_assign(db_interface['id'], network) self.interfaces.append(db_interface) if hostname: self._assign_addresses_to_interface(hostname, db_interface, networktype) db_interface.networktypelist = self._get_network_type_list(networktype) return db_interface def _create_vf_test(self, ifname, num_vfs, vf_driver=None, lower_iface=None, max_tx_rate=None): if not lower_iface: lower_port, lower_iface = self._create_ethernet_test( 'sriov', constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV) if not ifname: ifname = 'vf-' + lower_iface['ifname'] if not num_vfs: num_vfs = 1 networks = [] ifclass = constants.INTERFACE_CLASS_PCI_SRIOV interface_id = len(self.interfaces) interface = {'id': interface_id, 'uuid': str(uuid.uuid4()), 'forihostid': self.host.id, 'ifname': ifname, 'iftype': constants.INTERFACE_TYPE_VF, 'imac': '02:11:22:33:44:' + str(10 + interface_id), 'uses': [lower_iface['ifname']], 'used_by': [], 'ifclass': ifclass, 'networks': networks, 'networktype': constants.NETWORK_TYPE_PCI_SRIOV, 'imtu': 1500, 'sriov_numvfs': num_vfs, 'sriov_vf_driver': vf_driver, 'max_tx_rate': max_tx_rate} lower_iface['used_by'].append(interface['ifname']) db_interface = dbutils.create_test_interface(**interface) self.interfaces.append(db_interface) return db_interface def _create_test_host(self, personality, subfunction=None): subfunctions = [personality] if subfunction: subfunctions.append(subfunction) host = {'personality': personality, 'hostname': '%s-0' % personality, 'forisystemid': self.system.id, 'subfunctions': ",".join(subfunctions)} return dbutils.create_test_ihost(**host) def _create_address_for_interface(self, iface, networktype=None, family=None): if not networktype: if len(iface.networktypelist) > 0: networktype = iface.networktypelist[0] network = None if networktype: network = self._find_network_by_type(networktype) addrpool = None if network: addrpools = self._find_network_address_pools(network.id) if family: for pool in addrpools: if pool.family == family: addrpool = pool break elif len(addrpools) > 0: addrpool = addrpools[0] if addrpool: next_address = netaddr.IPAddress(addrpool.network) + 10 address_fields = {'interface_id': iface['id'], 'address_pool_id': addrpool.id, 'family': addrpool.family, 'prefix': addrpool.prefix, 'address': str(next_address)} else: if family == constants.IPV6_FAMILY: address_fields = {'family': constants.IPV6_FAMILY, 'prefix': 64, 'address': 'fd08::a'} else: address_fields = {'family': constants.IPV4_FAMILY, 'prefix': 24, 'address': '192.168.1.10'} address_fields['interface_id'] = iface['id'] address = dbutils.create_test_address(**address_fields) self.addresses.append(address) return network, address def _assign_addresses_to_pool(self): dbapi = db_api.get_instance() network_names = { 'oam': 'oam', 'mgmt': 'management', 'cluster-host': 'cluster-host', 'pxeboot': 'pxeboot', 'admin': 'admin' } addrpool_index = {} addrpools = dbapi.address_pools_get_all() for addrpool in addrpools: if addrpool.name: addrpool_index[addrpool.name] = ( addrpool, netaddr.IPNetwork(str(addrpool.network) + '/' + str(addrpool.prefix)) ) addresses = dbapi.addresses_get_all() for addr in addresses: if not addr.name: continue for network_type, network_name in network_names.items(): if addr.name.endswith("-" + network_type): pool_name = f"{network_name}-ipv{addr.family}" addrpool = addrpool_index.get(pool_name, None) if not addrpool: break ipaddr = netaddr.IPAddress(addr.address) if ipaddr not in addrpool[1]: break dbapi.address_update(addr.uuid, {'address_pool_id': addrpool[0].id}) break def _assign_addresses_to_interface(self, hostname, interface, networktypes): if isinstance(networktypes, list): networktypelist = networktypes elif networktypes: networktypelist = [networktypes] else: networktypelist = [] dbapi = db_api.get_instance() addresses = dbapi.addresses_get_all() name_index = { hostname + "-oam": constants.NETWORK_TYPE_OAM, hostname + "-mgmt": constants.NETWORK_TYPE_MGMT, hostname + "-cluster-host": constants.NETWORK_TYPE_CLUSTER_HOST, hostname + "-pxeboot": constants.NETWORK_TYPE_PXEBOOT, hostname + "-admin": constants.NETWORK_TYPE_ADMIN, } for network_type in networktypelist: for addr in addresses: if not (addr.name): continue try: if (name_index.get(addr.name, None) == network_type or (addr.ifname == interface.ifname and addr.interface_id is None)): dbapi.address_update(addr.uuid, {'interface_id': interface.id}) except Exception as ex: print(f"Failed to link address {addr.name} to interface " f"{interface.ifname}: {ex}") @puppet.puppet_context def _update_context(self): # interface is added as an operator by systemconfig.puppet_plugins self.context = \ self.operator.interface._create_interface_context(self.host) # pylint: disable=no-member # Update the puppet context with generated interface context self.operator.context.update(self.context) def _setup_context(self): self.ports = [] self.interfaces = [] self.addresses = [] self.routes = [] self._setup_configuration() self._update_context() def _setup_configuration(self): pass class InterfaceTestCase1(InterfaceTestCaseMixin, dbbase.BaseHostTestCase): def setUp(self): super(InterfaceTestCase1, self).setUp() self._setup_context() def _setup_configuration(self): self.host = self._create_test_host(constants.CONTROLLER) self.port, self.iface = self._create_ethernet_test( "mgmt0", constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT) self.mgmt_gateway_address = self.mgmt_subnet[1] self.oam_gateway_address = self.oam_subnet[1] def _update_context(self): super(InterfaceTestCase1, self)._update_context() def test_get_port_interface_id_index(self): index = self.operator.interface._get_port_interface_id_index(self.host) # pylint: disable=no-member for port in self.ports: self.assertTrue(port['interface_id'] in index) self.assertEqual(index[port['interface_id']], port) def test_get_port_pciaddr_index(self): index = self.operator.interface._get_port_pciaddr_index(self.host) # pylint: disable=no-member for port in self.ports: self.assertTrue(port['pciaddr'] in index) self.assertIn(port, index[port['pciaddr']]) def test_get_network_type_index(self): index = self.operator.interface._get_network_type_index() # pylint: disable=no-member for network in self._get_all_networks(): self.assertTrue(network['type'] in index) self.assertEqual(index[network['type']], network) def test_get_address_interface_name_index(self): index = self.operator.interface._get_address_interface_name_index(self.host) # pylint: disable=no-member for address in self.addresses: self.assertTrue(address['ifname'] in index) self.assertIn(address, index[address['ifname']]) def test_get_routes_interface_name_index(self): index = self.operator.interface._get_routes_interface_name_index(self.host) # pylint: disable=no-member for route in self.routes: self.assertTrue(route['ifname'] in index) self.assertIn(route, index[route['ifname']]) def test_get_interface_mtu(self): value = interface.get_interface_mtu(self.context, self.iface) self.assertEqual(value, self.iface['imtu']) def test_get_interface_port(self): value = interface.get_interface_port(self.context, self.iface) self.assertEqual(value, self.port) def test_get_interface_port_name(self): value = interface.get_interface_port_name(self.context, self.iface) self.assertEqual(value, self.port['name']) def test_get_interface_os_ifname_ethernet(self): value = interface.get_interface_os_ifname(self.context, self.iface) self.assertEqual(value, self.port['name']) def test_get_interface_os_ifname_bond(self): self.iface['iftype'] = constants.INTERFACE_TYPE_AE value = interface.get_interface_os_ifname(self.context, self.iface) self.assertEqual(value, self.iface['ifname']) def _get_route_config(self, name='default', ensure='present', gateway='1.2.3.1', interface='eth0', netmask='0.0.0.0', network='default', metric=1): config = {'name': name, 'ensure': ensure, 'gateway': gateway, 'interface': interface, 'netmask': netmask, 'network': network, 'options': 'metric ' + str(metric)} return config def test_get_route_config(self): route = {'network': '1.2.3.0', 'prefix': 24, 'gateway': '1.2.3.1', 'metric': 20} config = interface.get_route_config(route, "eth0") expected = self._get_route_config( name='1.2.3.0/24', network='1.2.3.0', netmask='255.255.255.0', metric=20) self.assertEqual(expected, config) def test_get_route_config_default(self): route = {'network': '0.0.0.0', 'prefix': 0, 'gateway': '1.2.3.1', 'metric': 1} config = interface.get_route_config(route, "eth0") expected = self._get_route_config() self.assertEqual(expected, config) def test_is_an_n3000_i40_device_false(self): self.assertFalse( interface.is_an_n3000_i40_device(self.context, self.iface)) def test_find_sriov_interfaces_by_driver_none(self): ifaces = interface.find_sriov_interfaces_by_driver( self.context, constants.DRIVER_MLX_CX4) self.assertTrue(not ifaces) class InterfaceTestCase2(InterfaceTestCaseMixin, dbbase.BaseHostTestCase): def setUp(self): super(InterfaceTestCase2, self).setUp() self._setup_context() def _setup_configuration(self): pass def _update_context(self): # skip automatic context update, context updates will be invoked individually # in each test function, via the self._do_update_context() method pass def _do_update_context(self): super(InterfaceTestCase2, self)._update_context() def _create_host(self, personality, subfunction=None): self.host = self._create_test_host(personality, subfunction) def _create_host_and_interface(self, ifclass, networktype, **kwargs): self.host = self._create_test_host( kwargs.get('personality', constants.CONTROLLER), kwargs.get('subfunction', None)) self.port, self.iface = self._create_ethernet_test( kwargs.get('name', 'mgmt0'), ifclass, networktype, **kwargs) def _set_address_mode(self, iface, ipv4_mode=constants.IPV4_DISABLED, ipv6_mode=constants.IPV6_DISABLED): self.dbapi.address_mode_update(iface.id, {'family': constants.IPV4_FAMILY, 'mode': ipv4_mode}) self.dbapi.address_mode_update(iface.id, {'family': constants.IPV6_FAMILY, 'mode': ipv6_mode}) iface.ipv4_mode = ipv4_mode iface.ipv6_mode = ipv6_mode def test_is_platform_network_type_true(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT) self._do_update_context() result = interface.is_platform_network_type(self.iface) self.assertTrue(result) def test_is_platform_network_type_false(self): self._create_host_and_interface( constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA) self._do_update_context() result = interface.is_platform_network_type(self.iface) self.assertFalse(result) def test_is_worker_subfunction_true(self): self._create_host(constants.WORKER) self._do_update_context() self.assertTrue(interface.is_worker_subfunction(self.context)) def test_is_worker_subfunction_true_cpe(self): self._create_host(constants.CONTROLLER, constants.WORKER) self._do_update_context() self.assertTrue(interface.is_worker_subfunction(self.context)) def test_is_worker_subfunction_false(self): self._create_host(constants.STORAGE) self._do_update_context() self.assertFalse(interface.is_worker_subfunction(self.context)) def test_is_worker_subfunction_false_cpe(self): self._create_host(constants.CONTROLLER) self._do_update_context() self.assertFalse(interface.is_worker_subfunction(self.context)) def test_is_pci_interface_true(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV) self._do_update_context() self.assertTrue(interface.is_pci_interface(self.iface)) def test_is_pci_interface_false(self): self._create_host_and_interface( constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA) self._do_update_context() self.assertFalse(interface.is_pci_interface(self.iface)) def test_get_lower_interface_vlan(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT) vlan = self._create_vlan_test( "cluster-host", constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_CLUSTER_HOST, 1, self.iface) self._do_update_context() value = interface.get_lower_interface(self.context, vlan) self.assertEqual(value, self.iface) def test_get_lower_interface_vf(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV, name='sriov1', sriov_numvfs=2) vf = self._create_vf_test("vf1", 1, None, lower_iface=self.iface) self._do_update_context() value = interface.get_lower_interface(self.context, vf) self.assertEqual(value, self.iface) def test_get_interface_os_ifname_vlan_over_ethernet(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT) vlan1 = self._create_vlan_test( "cluster-host", constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_CLUSTER_HOST, 1, self.iface) vlan2 = self._create_vlan_test( "testvlan", constants.INTERFACE_CLASS_NONE, constants.NETWORK_TYPE_CLUSTER_HOST, 1, self.iface) vlan3 = self._create_vlan_test( "vlan999", constants.INTERFACE_CLASS_NONE, constants.NETWORK_TYPE_CLUSTER_HOST, 1, self.iface) vlan4 = self._create_vlan_test( "testvlan.999", constants.INTERFACE_CLASS_NONE, constants.NETWORK_TYPE_CLUSTER_HOST, 1, self.iface) self._do_update_context() self.assertEqual(interface.get_interface_os_ifname(self.context, vlan1), "vlan1") self.assertEqual(interface.get_interface_os_ifname(self.context, vlan2), "testvlan") self.assertEqual(interface.get_interface_os_ifname(self.context, vlan3), "vlan#999") self.assertEqual(interface.get_interface_os_ifname(self.context, vlan4), "testvlan#999") def test_get_interface_os_ifname_vlan_over_bond(self): self._create_host(constants.CONTROLLER) bond = self._create_bond_test("none") vlan = self._create_vlan_test( "cluster-host", constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_CLUSTER_HOST, 1, bond) self._do_update_context() value = interface.get_interface_os_ifname(self.context, vlan) self.assertEqual(value, "vlan1") def test_get_gateway_address_oam(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_OAM) network, address = self._create_address_for_interface(self.iface) self._do_update_context() gateway = interface.get_gateway_address(self.context, network, address) expected = str(self.oam_subnet[1]) self.assertEqual(gateway, expected) def test_get_gateway_address_mgmt(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT) network, address = self._create_address_for_interface(self.iface) self._do_update_context() gateway = interface.get_gateway_address(self.context, network, address) expected = str(self.mgmt_subnet[1]) self.assertEqual(gateway, expected) def test_get_interface_address_method_for_none(self): self._create_host_and_interface( constants.INTERFACE_CLASS_NONE, constants.NETWORK_TYPE_NONE) self._do_update_context() method = interface.get_interface_address_method( self.context, self.iface) self.assertEqual(method, 'manual') def test_get_interface_address_method_for_data(self): self._create_host_and_interface( constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA) _, address_ipv4 = self._create_address_for_interface( self.iface, family=constants.IPV4_FAMILY) _, address_ipv6 = self._create_address_for_interface( self.iface, family=constants.IPV6_FAMILY) self._do_update_context() self.iface['ipv4_mode'] = constants.IPV4_DISABLED self.iface['ipv6_mode'] = constants.IPV6_DISABLED method = interface.get_interface_address_method( self.context, self.iface) self.assertEqual(method, 'manual') self.iface['ipv4_mode'] = constants.IPV4_STATIC self.iface['ipv6_mode'] = constants.IPV6_DISABLED method = interface.get_interface_address_method( self.context, self.iface) self.assertEqual(method, 'manual') self.iface['ipv4_mode'] = constants.IPV4_DISABLED self.iface['ipv6_mode'] = constants.IPV6_STATIC method = interface.get_interface_address_method( self.context, self.iface) self.assertEqual(method, 'manual') self.iface['ipv4_mode'] = constants.IPV4_STATIC self.iface['ipv6_mode'] = constants.IPV6_STATIC method = interface.get_interface_address_method( self.context, self.iface) self.assertEqual(method, 'manual') self.iface['ipv4_mode'] = constants.IPV4_DISABLED self.iface['ipv6_mode'] = constants.IPV6_DISABLED method = interface.get_interface_address_method( self.context, self.iface, None, address_ipv4) self.assertEqual(method, 'manual') self.iface['ipv4_mode'] = constants.IPV4_STATIC self.iface['ipv6_mode'] = constants.IPV6_DISABLED method = interface.get_interface_address_method( self.context, self.iface, None, address_ipv4) self.assertEqual(method, 'static') self.iface['ipv4_mode'] = constants.IPV4_DISABLED self.iface['ipv6_mode'] = constants.IPV6_STATIC method = interface.get_interface_address_method( self.context, self.iface, None, address_ipv4) self.assertEqual(method, 'manual') self.iface['ipv4_mode'] = constants.IPV4_STATIC self.iface['ipv6_mode'] = constants.IPV6_STATIC method = interface.get_interface_address_method( self.context, self.iface, None, address_ipv4) self.assertEqual(method, 'static') self.iface['ipv4_mode'] = constants.IPV4_DISABLED self.iface['ipv6_mode'] = constants.IPV6_DISABLED method = interface.get_interface_address_method( self.context, self.iface, None, address_ipv6) self.assertEqual(method, 'manual') self.iface['ipv4_mode'] = constants.IPV4_STATIC self.iface['ipv6_mode'] = constants.IPV6_DISABLED method = interface.get_interface_address_method( self.context, self.iface, None, address_ipv6) self.assertEqual(method, 'manual') self.iface['ipv4_mode'] = constants.IPV4_DISABLED self.iface['ipv6_mode'] = constants.IPV6_STATIC method = interface.get_interface_address_method( self.context, self.iface, None, address_ipv6) self.assertEqual(method, 'static') self.iface['ipv4_mode'] = constants.IPV4_STATIC self.iface['ipv6_mode'] = constants.IPV6_STATIC method = interface.get_interface_address_method( self.context, self.iface, None, address_ipv6) self.assertEqual(method, 'static') def test_get_interface_address_method_for_pci_sriov(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV) self._do_update_context() method = interface.get_interface_address_method( self.context, self.iface) self.assertEqual(method, 'manual') def test_get_interface_address_method_for_pci_pthru(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PCI_PASSTHROUGH, constants.NETWORK_TYPE_PCI_PASSTHROUGH) self._do_update_context() method = interface.get_interface_address_method( self.context, self.iface) self.assertEqual(method, 'manual') def test_get_interface_address_method_for_pxeboot_worker(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_PXEBOOT, personality=constants.WORKER) self._do_update_context() network = self._find_network_by_type(constants.NETWORK_TYPE_PXEBOOT) method = interface.get_interface_address_method( self.context, self.iface, network) self.assertEqual(method, 'dhcp') def test_get_interface_address_method_for_pxeboot_storage(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_PXEBOOT, personality=constants.STORAGE) self._do_update_context() network = self._find_network_by_type(constants.NETWORK_TYPE_PXEBOOT) method = interface.get_interface_address_method( self.context, self.iface, network) self.assertEqual(method, 'dhcp') def test_get_interface_address_method_for_pxeboot_controller(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_PXEBOOT) self._do_update_context() network = self._find_network_by_type(constants.NETWORK_TYPE_PXEBOOT) method = interface.get_interface_address_method( self.context, self.iface, network) self.assertEqual(method, 'static') def test_get_interface_address_method_for_mgmt_worker(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT, personality=constants.WORKER) self._do_update_context() network = self._find_network_by_type(constants.NETWORK_TYPE_MGMT) method = interface.get_interface_address_method( self.context, self.iface, network) self.assertEqual(method, 'static') def test_get_interface_address_method_for_mgmt_storage(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT, personality=constants.STORAGE) self._do_update_context() network = self._find_network_by_type(constants.NETWORK_TYPE_MGMT) method = interface.get_interface_address_method( self.context, self.iface, network) self.assertEqual(method, 'static') def test_get_interface_address_method_for_mgmt_controller(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT) self._do_update_context() network = self._find_network_by_type(constants.NETWORK_TYPE_MGMT) method = interface.get_interface_address_method( self.context, self.iface, network) self.assertEqual(method, 'static') def test_get_interface_address_method_for_cluster_host_worker(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT, personality=constants.WORKER) self._do_update_context() network = self._find_network_by_type(constants.NETWORK_TYPE_CLUSTER_HOST) method = interface.get_interface_address_method( self.context, self.iface, network) self.assertEqual(method, 'static') def test_get_interface_address_method_for_cluster_host_storage(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_CLUSTER_HOST, personality=constants.STORAGE) self._do_update_context() network = self._find_network_by_type(constants.NETWORK_TYPE_CLUSTER_HOST) method = interface.get_interface_address_method( self.context, self.iface, network) self.assertEqual(method, 'static') def test_get_interface_address_method_for_cluster_host_controller(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_CLUSTER_HOST) self._do_update_context() network = self._find_network_by_type(constants.NETWORK_TYPE_CLUSTER_HOST) method = interface.get_interface_address_method( self.context, self.iface, network) self.assertEqual(method, 'static') def test_get_interface_address_method_for_oam_controller(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_OAM) self._do_update_context() network = self._find_network_by_type(constants.NETWORK_TYPE_OAM) method = interface.get_interface_address_method( self.context, self.iface, network) self.assertEqual(method, 'static') def test_get_interface_address_method_for_platform_ipv4(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_NONE) network, address = self._create_address_for_interface(self.iface) self._set_address_mode(self.iface, ipv4_mode=constants.IPV4_STATIC) self._do_update_context() method = interface.get_interface_address_method( self.context, self.iface, network, address) self.assertEqual(method, 'static') def test_get_interface_address_method_for_platform_ipv6(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_NONE) network, address = self._create_address_for_interface( self.iface, family=constants.IPV6_FAMILY) self._set_address_mode(self.iface, ipv6_mode=constants.IPV6_STATIC) self._do_update_context() method = interface.get_interface_address_method( self.context, self.iface, network, address) self.assertEqual(method, 'static') def test_get_interface_address_method_for_platform_base(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PLATFORM, [constants.NETWORK_TYPE_MGMT, constants.NETWORK_TYPE_CLUSTER_HOST]) self._do_update_context() method = interface.get_interface_address_method( self.context, self.iface) self.assertEqual(method, 'manual') def test_get_interface_address_method_for_platform_invalid(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_OAM, personality=constants.WORKER) self._set_address_mode(self.iface, ipv4_mode=constants.IPV4_STATIC) self._do_update_context() network = self._find_network_by_type(constants.NETWORK_TYPE_OAM) method = interface.get_interface_address_method( self.context, self.iface, network) self.assertEqual(method, 'dhcp') def test_get_interface_traffic_classifier_for_mgmt(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT) self._do_update_context() classifier = interface.get_interface_traffic_classifier( self.context, self.iface) expected = ('%s %s %s %s > /dev/null' % (constants.TRAFFIC_CONTROL_SCRIPT, self.port['name'], constants.NETWORK_TYPE_MGMT, constants.LINK_SPEED_10G)) self.assertEqual(classifier, expected) def test_get_interface_traffic_classifier_for_cluster_host(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_CLUSTER_HOST) self._do_update_context() classifier = interface.get_interface_traffic_classifier( self.context, self.iface) self.assertIsNone(classifier) def test_get_interface_traffic_classifier_for_oam(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_OAM) self._do_update_context() classifier = interface.get_interface_traffic_classifier( self.context, self.iface) self.assertIsNone(classifier) def test_get_interface_traffic_classifier_for_none(self): self._create_host_and_interface( constants.INTERFACE_CLASS_NONE, constants.NETWORK_TYPE_NONE) self._do_update_context() classifier = interface.get_interface_traffic_classifier( self.context, self.iface) self.assertIsNone(classifier) def test_get_sriov_interface_device_id(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV, name='sriov1', sriov_numvfs=2) self._do_update_context() value = interface.get_sriov_interface_device_id(self.context, self.iface) self.assertEqual(value, '1572') def test_get_sriov_interface_port(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV, name='sriov1', sriov_numvfs=2) vf = self._create_vf_test("vf1", 1, None, lower_iface=self.iface) self._do_update_context() value = interface.get_sriov_interface_port(self.context, vf) self.assertEqual(value, self.port) def test_get_sriov_interface_port_invalid(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PCI_PASSTHROUGH, constants.NETWORK_TYPE_PCI_PASSTHROUGH, name='pthru') self._do_update_context() self.assertRaises(AssertionError, interface.get_sriov_interface_port, self.context, self.iface) def test_get_sriov_interface_vf_addrs(self): vf_addr1 = "0000:81:00.0" vf_addr2 = "0000:81:01.0" vf_addr_list = [vf_addr1, vf_addr2] self._create_host_and_interface( constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV, name='sriov1', sriov_numvfs=2) vf1 = self._create_vf_test("vf1", 1, None, lower_iface=self.iface) self._do_update_context() addrs1 = interface.get_sriov_interface_vf_addrs( self.context, self.iface, vf_addr_list) self.assertEqual(len(addrs1), 1) addrs2 = interface.get_sriov_interface_vf_addrs( self.context, vf1, vf_addr_list) self.assertEqual(len(addrs2), 1) def test_get_sriov_interface_vf_addrs_multiple_children(self): vf_addr1 = "0000:81:00.0" vf_addr2 = "0000:81:01.0" vf_addr3 = "0000:81:02.0" vf_addr_list = [vf_addr1, vf_addr2, vf_addr3] self._create_host_and_interface( constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV, name='sriov1', sriov_numvfs=3) vf1 = self._create_vf_test("vf1", 1, None, lower_iface=self.iface) vf2 = self._create_vf_test("vf2", 1, None, lower_iface=self.iface) self._do_update_context() addrs1 = interface.get_sriov_interface_vf_addrs( self.context, vf1, vf_addr_list) self.assertEqual(len(addrs1), 1) addrs2 = interface.get_sriov_interface_vf_addrs( self.context, vf2, vf_addr_list) self.assertEqual(len(addrs2), 1) addrs3 = interface.get_sriov_interface_vf_addrs( self.context, self.iface, vf_addr_list) self.assertEqual(len(addrs3), 1) def test_get_sriov_interface_vf_addrs_multiple_parents(self): vf_addr1 = "0000:81:00.0" vf_addr2 = "0000:81:01.0" vf_addr3 = "0000:81:02.0" vf_addr_list = [vf_addr1, vf_addr2, vf_addr3] self._create_host_and_interface( constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV, name='sriov1', sriov_numvfs=3) vf1 = self._create_vf_test("vf1", 2, None, lower_iface=self.iface) vf2 = self._create_vf_test("vf2", 1, None, lower_iface=vf1) self._do_update_context() addrs1 = interface.get_sriov_interface_vf_addrs( self.context, vf1, vf_addr_list) self.assertEqual(len(addrs1), 1) addrs2 = interface.get_sriov_interface_vf_addrs( self.context, vf2, vf_addr_list) self.assertEqual(len(addrs2), 1) addrs3 = interface.get_sriov_interface_vf_addrs( self.context, self.iface, vf_addr_list) self.assertEqual(len(addrs3), 1) def test_get_bridge_interface_name_none_dpdk_supported(self): self._create_host_and_interface( constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA, dpdksupport=True) self._do_update_context() ifname = interface.get_bridge_interface_name(self.context, self.iface) self.assertIsNone(ifname) def test_get_bridge_interface_name_none_not_data(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT) self._do_update_context() ifname = interface.get_bridge_interface_name(self.context, self.iface) self.assertIsNone(ifname) def test_get_bridge_interface_name(self): self._create_host_and_interface( constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA, dpdksupport=False) self._do_update_context() ifname = interface.get_bridge_interface_name(self.context, self.iface) self.assertEqual(ifname, 'br-' + self.port['name']) def test_needs_interface_config_kernel_mgmt(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT) self._do_update_context() needed = interface.needs_interface_config(self.context, self.iface) self.assertTrue(needed) def test_needs_interface_config_kernel_cluster_host(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_CLUSTER_HOST) self._do_update_context() needed = interface.needs_interface_config(self.context, self.iface) self.assertTrue(needed) def test_needs_interface_config_kernel_oam(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_OAM) self._do_update_context() needed = interface.needs_interface_config(self.context, self.iface) self.assertTrue(needed) def test_needs_interface_config_data(self): self._create_host_and_interface( constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA, dpdksupport=True) self._do_update_context() needed = interface.needs_interface_config(self.context, self.iface) self.assertFalse(needed) def test_needs_interface_config_data_slow(self): self._create_host_and_interface( constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA, dpdksupport=False) self._do_update_context() needed = interface.needs_interface_config(self.context, self.iface) self.assertFalse(needed) def test_needs_interface_config_data_mlx5(self): self._create_host_and_interface( constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA, driver=constants.DRIVER_MLX_CX4) self._do_update_context() needed = interface.needs_interface_config(self.context, self.iface) self.assertFalse(needed) def test_needs_interface_config_data_slow_worker(self): self._create_host_and_interface( constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA, personality=constants.WORKER, dpdksupport=False) self._do_update_context() needed = interface.needs_interface_config(self.context, self.iface) self.assertTrue(needed) def test_needs_interface_config_data_mlx5_worker(self): self._create_host_and_interface( constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA, personality=constants.WORKER, driver=constants.DRIVER_MLX_CX4) self._do_update_context() needed = interface.needs_interface_config(self.context, self.iface) self.assertTrue(needed) def test_needs_interface_config_sriov_worker(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV, personality=constants.WORKER) self._do_update_context() needed = interface.needs_interface_config(self.context, self.iface) self.assertTrue(needed) def test_needs_interface_config_pthru_worker(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PCI_PASSTHROUGH, constants.NETWORK_TYPE_PCI_PASSTHROUGH, personality=constants.WORKER) self._do_update_context() needed = interface.needs_interface_config(self.context, self.iface) self.assertTrue(needed) def test_needs_interface_config_data_cpe_worker(self): self._create_host_and_interface( constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA, personality=constants.CONTROLLER, subfunction=constants.WORKER, dpdksupport=True) self._do_update_context() needed = interface.needs_interface_config(self.context, self.iface) self.assertFalse(needed) def test_needs_interface_config_data_slow_cpe_worker(self): self._create_host_and_interface( constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA, personality=constants.CONTROLLER, subfunction=constants.WORKER, dpdksupport=False) self._do_update_context() needed = interface.needs_interface_config(self.context, self.iface) self.assertTrue(needed) def test_needs_interface_config_data_mlx5_cpe_worker(self): self._create_host_and_interface( constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA, personality=constants.CONTROLLER, subfunction=constants.WORKER, driver=constants.DRIVER_MLX_CX4) self._do_update_context() needed = interface.needs_interface_config(self.context, self.iface) self.assertTrue(needed) def test_needs_interface_config_sriov_cpe(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV) self._do_update_context() needed = interface.needs_interface_config(self.context, self.iface) self.assertFalse(needed) def test_needs_interface_config_sriov_cpe_worker(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV, personality=constants.CONTROLLER, subfunction=constants.WORKER) self._do_update_context() needed = interface.needs_interface_config(self.context, self.iface) self.assertTrue(needed) def test_needs_interface_config_pthru_cpe_worker(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PCI_PASSTHROUGH, constants.NETWORK_TYPE_PCI_PASSTHROUGH, personality=constants.CONTROLLER, subfunction=constants.WORKER) self._do_update_context() needed = interface.needs_interface_config(self.context, self.iface) self.assertTrue(needed) def _get_network_config_ifupdown(self, ifname='eth0', ensure='present', family='inet', method='dhcp', hotplug='false', onboot='true', ipaddress=None, netmask=None, options=None): config = {'ifname': ifname, 'ensure': ensure, 'family': family, 'method': method, 'hotplug': hotplug, 'onboot': onboot} if ipaddress: config['ipaddress'] = ipaddress if netmask: config['netmask'] = netmask config['options'] = options or {} return config def _get_static_network_config_ifupdown(self, **kwargs): ifname = kwargs.pop('ifname', 'eth0') method = kwargs.pop('method', 'static') ipaddress = kwargs.pop('ipaddress', '192.168.1.2') netmask = kwargs.pop('netmask', '255.255.255.0') return self._get_network_config_ifupdown( ifname=ifname, method=method, ipaddress=ipaddress, netmask=netmask, **kwargs) def _get_sriov_config(self, ifname='default', vf_driver=constants.SRIOV_DRIVER_TYPE_VFIO, num_vfs=2, pf_addr=None, device_id='1572', port_name="eth0", up_requirement=False, vf_config=None): if vf_config is None: vf_config = {} config = {'ifname': ifname, 'addr': pf_addr if pf_addr else self.port['pciaddr'], 'device_id': device_id, 'num_vfs': num_vfs, 'port_name': port_name, 'up_requirement': up_requirement, 'vf_config': vf_config} return config def _get_fpga_config(self, portname='eth1', device_id='0d58', vlans=None): config = { 'ifname': portname, 'device_id': device_id, 'used_by': vlans } return config def _get_loopback_config(self): network_config = self._get_network_config_ifupdown( ifname=interface.LOOPBACK_IFNAME, method=interface.LOOPBACK_METHOD) return interface.format_network_config(network_config) def _get_ipv6_autoconf_off(self, os_ifname): autoconf_off = 'echo 0 > /proc/sys/net/ipv6/conf/{}/autoconf'.format(os_ifname) accept_ra_off = 'echo 0 > /proc/sys/net/ipv6/conf/{}/accept_ra'.format(os_ifname) accept_redir_off = 'echo 0 > /proc/sys/net/ipv6/conf/{}/accept_redirects'.format(os_ifname) ipv6_autocnf_off = '{}; {}; {}'.format(autoconf_off, accept_ra_off, accept_redir_off) return ipv6_autocnf_off def _get_postup_mtu(self, os_ifname, mtu): set_mtu = '/usr/sbin/ip link set dev {} mtu {}'.format(os_ifname, mtu) postup_mtu = '{};'.format(set_mtu) return postup_mtu def test_generate_loopback_config(self): config = { interface.NETWORK_CONFIG_RESOURCE: {}, } interface.generate_loopback_config(config) expected = self._get_loopback_config() result = config[interface.NETWORK_CONFIG_RESOURCE].get( interface.LOOPBACK_IFNAME) self.assertEqual(result, expected) def test_get_controller_ethernet_config_oam_ifupdown(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_OAM) network, address = self._create_address_for_interface(self.iface) self._do_update_context() configs = interface.get_interface_network_configs( self.context, self.iface, network) ipv6_autocnf_off = self._get_ipv6_autoconf_off(self.port['name']) options = {'stx-description': 'ifname:mgmt0,net:oam', 'post-up': '{}'.format(ipv6_autocnf_off), 'mtu': '1500', 'gateway': '10.10.10.1'} expected = self._get_static_network_config_ifupdown( ipaddress='10.10.10.10', ifname=f"{self.port['name']}:{network.id}-{address.id}", options=options) self.assertEqual(expected, configs[0]) def test_get_controller_ethernet_config_mgmt_ifupdown(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT) network, address = self._create_address_for_interface(self.iface) self._do_update_context() configs = interface.get_interface_network_configs( self.context, self.iface, network) ipv6_autocnf_off = self._get_ipv6_autoconf_off(self.port['name']) options = {'post-up': '%s' % ipv6_autocnf_off, 'mtu': '1500', 'stx-description': 'ifname:mgmt0,net:mgmt', 'gateway': '192.168.204.1'} expected = self._get_static_network_config_ifupdown( ipaddress='192.168.204.10', ifname=f"{self.port['name']}:{network.id}-{address.id}", options=options) self.assertEqual(expected, configs[0]) def test_get_controller_ethernet_config_cluster_host_ifupdown(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_CLUSTER_HOST) network, address = self._create_address_for_interface(self.iface) self._do_update_context() configs = interface.get_interface_network_configs( self.context, self.iface, network) ipv6_autocnf_off = self._get_ipv6_autoconf_off(self.port['name']) options = {'stx-description': 'ifname:mgmt0,net:cluster-host', 'post-up': '{}'.format(ipv6_autocnf_off), 'mtu': '1500', 'gateway': '192.168.206.1'} expected = self._get_static_network_config_ifupdown( ipaddress='192.168.206.10', ifname=f"{self.port['name']}:{network.id}-{address.id}", options=options) self.assertEqual(expected, configs[0]) def test_get_controller_ethernet_config_slave_ifupdown(self): self._create_host(constants.CONTROLLER) bond = self._create_bond_test("bond0") self._do_update_context() iface = self.context['interfaces'][bond['uses'][0]] port = self.context['ports'][iface['id']] configs = interface.get_interface_network_configs(self.context, iface) ipv6_autocnf_off = self._get_ipv6_autoconf_off(port['name']) options = {'allow-bond0': port['name'], 'bond-master': 'bond0', 'stx-description': 'ifname:eth0,net:None', 'pre-up': '/usr/sbin/ip link set dev {} promisc on; {}'.format(port['name'], ipv6_autocnf_off), 'mtu': '1500'} expected = self._get_network_config_ifupdown( ifname=port['name'], method='manual', options=options) self.assertEqual(expected, configs[0]) def test_get_controller_ethernet_config_slave_sriov_bond(self): self._create_host(constants.CONTROLLER) port1, iface1 = self._create_ethernet_test( ifclass=constants.INTERFACE_CLASS_PCI_SRIOV, sriov_numvfs=16) port2, iface2 = self._create_ethernet_test( ifclass=constants.INTERFACE_CLASS_PCI_SRIOV, sriov_numvfs=16) self._create_bond_test("bond0", ifclass=constants.INTERFACE_CLASS_PLATFORM, iface1=iface1, iface2=iface2, aemode='active_standby', primary_reselect=constants.PRIMARY_RESELECT_ALWAYS) self._do_update_context() iface = iface1 port = port1 configs = interface.get_interface_network_configs(self.context, iface) numvfs_path = '/sys/class/net/{}/device/sriov_numvfs'.format(port['name']) numvfs_cmd = 'echo 0 > {0}; echo 16 > {0}'.format(numvfs_path) ipv6_autocnf_off = self._get_ipv6_autoconf_off(port['name']) options = {'allow-bond0': port['name'], 'bond-master': 'bond0', 'stx-description': 'ifname:{},net:None'.format(iface.ifname), 'pre-up': '/usr/sbin/ip link set dev {} promisc on; {}; {}'.format( port['name'], numvfs_cmd, ipv6_autocnf_off), 'mtu': '1500'} expected = self._get_network_config_ifupdown(ifname=port['name'], method='manual', options=options) self.assertEqual(expected, configs[0]) iface = iface2 port = port2 configs = interface.get_interface_network_configs(self.context, iface) numvfs_path = '/sys/class/net/{}/device/sriov_numvfs'.format(port['name']) numvfs_cmd = 'echo 0 > {0}; echo 16 > {0}'.format(numvfs_path) ipv6_autocnf_off = self._get_ipv6_autoconf_off(port['name']) options = {'allow-bond0': port['name'], 'bond-master': 'bond0', 'stx-description': 'ifname:{},net:None'.format(iface.ifname), 'pre-up': '/usr/sbin/ip link set dev {} promisc on; {}; {}'.format( port['name'], numvfs_cmd, ipv6_autocnf_off), 'mtu': '1500'} expected = self._get_network_config_ifupdown(ifname=port['name'], method='manual', options=options) self.assertEqual(expected, configs[0]) def test_get_controller_bond_config_duplex_ifupdown(self): self._create_host(constants.CONTROLLER) system_dict = self.system.as_dict() system_dict['system_mode'] = constants.SYSTEM_MODE_DUPLEX self.dbapi.isystem_update(self.system.uuid, system_dict) bond = self._create_bond_test( "bond0", ifclass=constants.INTERFACE_CLASS_PLATFORM, networktype=constants.NETWORK_TYPE_MGMT) network, address = self._create_address_for_interface(bond) self._do_update_context() configs = interface.get_interface_network_configs(self.context, bond, network) options = {'bond-lacp-rate': 'fast', 'bond-miimon': '100', 'bond-mode': '802.3ad', 'bond-slaves': 'eth0 eth1 ', 'bond-xmit-hash-policy': 'layer2', 'stx-description': 'ifname:bond0,net:mgmt', 'gateway': '192.168.204.1', 'hwaddress': '02:11:22:33:44:12', 'mtu': '1500', 'post-up': 'echo 0 > /proc/sys/net/ipv6/conf/bond0/autoconf; echo ' '0 > /proc/sys/net/ipv6/conf/bond0/accept_ra; echo 0 > ' '/proc/sys/net/ipv6/conf/bond0/accept_redirects', 'up': 'sleep 10'} expected = self._get_static_network_config_ifupdown( ipaddress='192.168.204.10', ifname=f"{bond['ifname']}:{network.id}-{address.id}", options=options) self.assertEqual(expected, configs[0]) def test_get_controller_bond_config_duplex_direct_ifupdown(self): self._create_host(constants.CONTROLLER) system_dict = self.system.as_dict() system_dict['system_mode'] = constants.SYSTEM_MODE_DUPLEX_DIRECT self.dbapi.isystem_update(self.system.uuid, system_dict) bond = self._create_bond_test( "bond0", ifclass=constants.INTERFACE_CLASS_PLATFORM, networktype=constants.NETWORK_TYPE_MGMT) network, address = self._create_address_for_interface(bond) self._do_update_context() network = self.dbapi.network_get_by_type(constants.NETWORK_TYPE_MGMT) configs = interface.get_interface_network_configs(self.context, bond) options = {'bond-lacp-rate': 'fast', 'bond-miimon': '100', 'bond-mode': '802.3ad', 'bond-slaves': 'eth0 eth1 ', 'bond-xmit-hash-policy': 'layer2', 'stx-description': 'ifname:bond0,net:None', 'hwaddress': '02:11:22:33:44:12', 'mtu': '1500', 'post-up': '/usr/local/bin/tc_setup.sh bond0 mgmt 10000 > /dev/null; ' 'echo 0 > /proc/sys/net/ipv6/conf/bond0/autoconf; echo ' '0 > /proc/sys/net/ipv6/conf/bond0/accept_ra; echo 0 > ' '/proc/sys/net/ipv6/conf/bond0/accept_redirects', 'pre-up': '/sbin/modprobe bonding; grep bond0 ' '/sys/class/net/bonding_masters || echo +bond0 > ' '/sys/class/net/bonding_masters; sysctl -wq ' 'net.ipv6.conf.bond0.accept_dad=0', 'up': 'sleep 10'} expected = self._get_network_config_ifupdown( method='manual', ifname=f"{bond['ifname']}", options=options) self.assertEqual(expected, configs[0]) configs = interface.get_interface_network_configs(self.context, bond, network) options = {'bond-lacp-rate': 'fast', 'bond-miimon': '100', 'bond-mode': '802.3ad', 'bond-slaves': 'eth0 eth1 ', 'bond-xmit-hash-policy': 'layer2', 'stx-description': 'ifname:bond0,net:mgmt', 'gateway': '192.168.204.1', 'hwaddress': '02:11:22:33:44:12', 'mtu': '1500', 'post-up': 'echo 0 > /proc/sys/net/ipv6/conf/bond0/autoconf; echo ' '0 > /proc/sys/net/ipv6/conf/bond0/accept_ra; echo 0 > ' '/proc/sys/net/ipv6/conf/bond0/accept_redirects', 'up': 'sleep 10'} expected = self._get_static_network_config_ifupdown( ipaddress='192.168.204.10', ifname=f"{bond['ifname']}:{network.id}-{address.id}", options=options) self.assertEqual(expected, configs[0]) def test_get_controller_bond_config_balanced_ifupdown(self): self._create_host(constants.CONTROLLER) bond = self._create_bond_test("bond0") self._do_update_context() configs = interface.get_interface_network_configs(self.context, bond) ipv6_autocnf_off = self._get_ipv6_autoconf_off(bond['ifname']) options = {'bond-miimon': '100', 'bond-slaves': 'eth0 eth1 ', 'bond-mode': 'balance-xor', 'bond-xmit-hash-policy': 'layer2', 'stx-description': 'ifname:bond0,net:None', 'hwaddress': bond['imac'], 'mtu': '1500', 'post-up': '{}'.format(ipv6_autocnf_off), 'up': 'sleep 10'} expected = self._get_network_config_ifupdown( ifname=bond['ifname'], method='manual', options=options) self.assertEqual(expected, configs[0]) def test_get_controller_bond_config_8023ad_ifupdown(self): self._create_host(constants.CONTROLLER) bond = self._create_bond_test("bond0", aemode='802.3ad') self._do_update_context() configs = interface.get_interface_network_configs(self.context, bond) ipv6_autocnf_off = self._get_ipv6_autoconf_off(bond['ifname']) options = {'bond-lacp-rate': 'fast', 'bond-miimon': '100', 'bond-mode': '802.3ad', 'bond-slaves': 'eth0 eth1 ', 'bond-xmit-hash-policy': 'layer2', 'stx-description': 'ifname:bond0,net:None', 'hwaddress': bond['imac'], 'mtu': '1500', 'post-up': '{}'.format(ipv6_autocnf_off), 'up': 'sleep 10'} expected = self._get_network_config_ifupdown( ifname=bond['ifname'], method='manual', options=options) self.assertEqual(expected, configs[0]) def test_get_controller_bond_config_active_standby_ifupdown(self): self._create_host(constants.CONTROLLER) bond = self._create_bond_test( "bond0", aemode='active_standby', primary_reselect=constants.PRIMARY_RESELECT_ALWAYS) self._do_update_context() configs = interface.get_interface_network_configs(self.context, bond) ipv6_autocnf_off = self._get_ipv6_autoconf_off(bond['ifname']) options = {'bond-miimon': '100', 'bond-mode': 'active-backup', 'bond-slaves': 'eth0 eth1 ', 'bond-primary': 'eth0', 'bond-primary-reselect': 'always', 'stx-description': 'ifname:bond0,net:None', 'hwaddress': bond['imac'], 'mtu': '1500', 'post-up': '{}'.format(ipv6_autocnf_off), 'up': 'sleep 10'} expected = self._get_network_config_ifupdown( ifname=bond['ifname'], method='manual', options=options) self.assertEqual(expected, configs[0]) def test_get_controller_bond_config_active_standby_primary_reselect_ifupdown(self): self._create_host(constants.CONTROLLER) bond = self._create_bond_test( "bond0", constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT, aemode='active_standby', primary_reselect=constants.PRIMARY_RESELECT_BETTER) self._do_update_context() configs = interface.get_interface_network_configs(self.context, bond) ipv6_autocnf_off = self._get_ipv6_autoconf_off(bond['ifname']) options = {'bond-miimon': '100', 'bond-mode': 'active-backup', 'bond-slaves': 'eth0 eth1 ', 'bond-primary': 'eth0', 'bond-primary-reselect': 'better', 'stx-description': 'ifname:bond0,net:None', 'hwaddress': bond['imac'], 'mtu': '1500', 'post-up': '/usr/local/bin/tc_setup.sh bond0 mgmt 10000 > /dev/null; ' + '{}'.format(ipv6_autocnf_off), 'up': 'sleep 10'} expected = self._get_network_config_ifupdown( ifname=bond['ifname'], method='manual', options=options) self.assertEqual(expected, configs[0]) def test_get_controller_vlan_config_ifupdown(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT) vlan = self._create_vlan_test("vlan1", None, None, 1, self.iface) self._do_update_context() configs = interface.get_interface_network_configs(self.context, vlan) ipv6_autocnf_off = self._get_ipv6_autoconf_off("vlan#1") mtu = '1500' set_mtu = self._get_postup_mtu("vlan#1", mtu) options = {'stx-description': 'ifname:vlan1,net:None', 'mtu': mtu, 'post-down': 'ip link del vlan#1', 'pre-up': '/sbin/modprobe -q 8021q; ip link add link ' '{} name vlan#1 type vlan id 1'.format( self.port['name']), 'post-up': '{} {}'.format(set_mtu, ipv6_autocnf_off), 'vlan-raw-device': '{}'.format(self.port['name'])} expected = self._get_network_config_ifupdown( ifname="vlan#1", method='manual', options=options) self.assertEqual(expected, configs[0]) def test_get_controller_vlan_config_ifname_with_dot(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT) vlan = self._create_vlan_test("vlan.dot", None, None, 1, self.iface) self._do_update_context() configs = interface.get_interface_network_configs(self.context, vlan) ipv6_autocnf_off = self._get_ipv6_autoconf_off("vlan.dot") mtu = '1500' set_mtu = self._get_postup_mtu("vlan.dot", mtu) options = {'stx-description': 'ifname:vlan.dot,net:None', 'mtu': mtu, 'post-down': 'ip link del vlan.dot', 'pre-up': '/sbin/modprobe -q 8021q; ip link add link ' '{} name vlan.dot type vlan id 1'.format( self.port['name']), 'post-up': '{} {}'.format(set_mtu, ipv6_autocnf_off), 'vlan-raw-device': '{}'.format(self.port['name'])} expected = self._get_network_config_ifupdown( ifname="vlan.dot", method='manual', options=options) self.assertEqual(expected, configs[0]) def test_get_controller_vlan_config_duplex_direct_ifupdown(self): self._create_host_and_interface( constants.INTERFACE_CLASS_NONE, constants.NETWORK_TYPE_NONE) system_dict = self.system.as_dict() system_dict['system_mode'] = constants.SYSTEM_MODE_DUPLEX_DIRECT self.dbapi.isystem_update(self.system.uuid, system_dict) vlan = self._create_vlan_test( "vlan100", constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT, 100, self.iface) network, address = self._create_address_for_interface(vlan) self._do_update_context() configs = interface.get_interface_network_configs(self.context, vlan) options = {'stx-description': 'ifname:vlan100,net:None', 'mtu': '1500', 'post-down': 'ip link del vlan100', 'post-up': '/usr/local/bin/tc_setup.sh vlan100 mgmt 10000 > /dev/null; ' '/usr/sbin/ip link set dev vlan100 mtu 1500; echo 0 > ' '/proc/sys/net/ipv6/conf/vlan100/autoconf; echo 0 ' '> /proc/sys/net/ipv6/conf/vlan100/accept_ra; echo 0 > ' '/proc/sys/net/ipv6/conf/vlan100/accept_redirects', 'pre-up': '/sbin/modprobe -q 8021q; ip link add link ' '{} name vlan100 type vlan id 100; '.format( self.port['name']) + 'sysctl -wq net.ipv6.conf.vlan100.accept_dad=0', 'vlan-raw-device': '{}'.format(self.port['name'])} expected = self._get_network_config_ifupdown( method='manual', ifname="vlan100", options=options) self.assertEqual(expected, configs[0]) configs = interface.get_interface_network_configs(self.context, vlan, network) options = {'stx-description': 'ifname:vlan100,net:mgmt', 'gateway': '192.168.204.1', 'mtu': '1500', 'post-up': '/usr/sbin/ip link set dev vlan100 mtu 1500; echo 0 > ' '/proc/sys/net/ipv6/conf/vlan100/autoconf; echo 0 ' '> /proc/sys/net/ipv6/conf/vlan100/accept_ra; echo 0 > ' '/proc/sys/net/ipv6/conf/vlan100/accept_redirects', 'pre-up': '/sbin/modprobe -q 8021q', 'vlan-raw-device': '{}'.format(self.port['name'])} expected = self._get_static_network_config_ifupdown( ipaddress='192.168.204.10', ifname=f"vlan100:{network.id}-{address.id}", options=options) self.assertEqual(expected, configs[0]) def test_is_disable_dad_required(self): self._create_host_and_interface(constants.INTERFACE_CLASS_NONE, constants.NETWORK_TYPE_NONE) bond = self._create_bond_test("bond0", constants.INTERFACE_CLASS_PLATFORM) vlan = self._create_vlan_test("vlan100", constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT, 100, self.iface) mgmt_network = self._find_network_by_type(constants.NETWORK_TYPE_MGMT) clhost_network = self._find_network_by_type(constants.NETWORK_TYPE_CLUSTER_HOST) # Ethernet self.iface.networktypelist = [constants.NETWORK_TYPE_MGMT] self.assertTrue(interface.is_disable_dad_required(self.iface, None)) self.assertFalse(interface.is_disable_dad_required(self.iface, mgmt_network)) self.iface.networktypelist = [constants.NETWORK_TYPE_CLUSTER_HOST] self.assertTrue(interface.is_disable_dad_required(self.iface, None)) self.assertFalse(interface.is_disable_dad_required(self.iface, clhost_network)) self.iface.networktypelist = [constants.NETWORK_TYPE_MGMT, constants.NETWORK_TYPE_CLUSTER_HOST] self.assertTrue(interface.is_disable_dad_required(self.iface, None)) self.assertFalse(interface.is_disable_dad_required(self.iface, mgmt_network)) self.assertFalse(interface.is_disable_dad_required(self.iface, clhost_network)) # Bond bond.networktypelist = [constants.NETWORK_TYPE_MGMT] self.assertTrue(interface.is_disable_dad_required(bond, None)) self.assertFalse(interface.is_disable_dad_required(bond, mgmt_network)) bond.networktypelist = [constants.NETWORK_TYPE_CLUSTER_HOST] self.assertTrue(interface.is_disable_dad_required(bond, None)) self.assertFalse(interface.is_disable_dad_required(bond, clhost_network)) bond.networktypelist = [constants.NETWORK_TYPE_MGMT, constants.NETWORK_TYPE_CLUSTER_HOST] self.assertTrue(interface.is_disable_dad_required(bond, None)) self.assertFalse(interface.is_disable_dad_required(bond, mgmt_network)) self.assertFalse(interface.is_disable_dad_required(bond, clhost_network)) # VLAN vlan.networktypelist = [constants.NETWORK_TYPE_MGMT] self.assertTrue(interface.is_disable_dad_required(vlan, None)) self.assertFalse(interface.is_disable_dad_required(vlan, mgmt_network)) vlan.networktypelist = [constants.NETWORK_TYPE_CLUSTER_HOST] self.assertTrue(interface.is_disable_dad_required(vlan, None)) self.assertFalse(interface.is_disable_dad_required(vlan, clhost_network)) vlan.networktypelist = [constants.NETWORK_TYPE_MGMT, constants.NETWORK_TYPE_CLUSTER_HOST] self.assertTrue(interface.is_disable_dad_required(vlan, None)) self.assertFalse(interface.is_disable_dad_required(vlan, mgmt_network)) self.assertFalse(interface.is_disable_dad_required(vlan, clhost_network)) def test_get_controller_ethernet_config_duplex_direct_mgmt_only(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT) system_dict = self.system.as_dict() system_dict['system_mode'] = constants.SYSTEM_MODE_DUPLEX_DIRECT self.dbapi.isystem_update(self.system.uuid, system_dict) network, address = self._create_address_for_interface(self.iface) self._do_update_context() configs = interface.get_interface_network_configs( self.context, self.iface) ipv6_autocnf_off = self._get_ipv6_autoconf_off(self.port['name']) options = {'post-up': '/usr/local/bin/tc_setup.sh eth0 mgmt 10000 > /dev/null; ' + '{}'.format(ipv6_autocnf_off), 'pre-up': 'sysctl -wq net.ipv6.conf.{}.accept_dad=0'.format(self.port['name']), 'mtu': '1500', 'stx-description': 'ifname:mgmt0,net:None'} expected = self._get_network_config_ifupdown( method='manual', ifname=f"{self.port['name']}", options=options) self.assertEqual(expected, configs[0]) configs = interface.get_interface_network_configs( self.context, self.iface, network) ipv6_autocnf_off = self._get_ipv6_autoconf_off(self.port['name']) options = {'post-up': '%s' % ipv6_autocnf_off, 'mtu': '1500', 'stx-description': 'ifname:mgmt0,net:mgmt', 'gateway': '192.168.204.1'} expected = self._get_static_network_config_ifupdown( ipaddress='192.168.204.10', ifname=f"{self.port['name']}:{network.id}-{address.id}", options=options) self.assertEqual(expected, configs[0]) def test_get_controller_ethernet_config_duplex_direct_mgmt_plus_cluster_host(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PLATFORM, [constants.NETWORK_TYPE_MGMT, constants.NETWORK_TYPE_CLUSTER_HOST]) system_dict = self.system.as_dict() system_dict['system_mode'] = constants.SYSTEM_MODE_DUPLEX_DIRECT self.dbapi.isystem_update(self.system.uuid, system_dict) mgmt_network, mgmt_address = self._create_address_for_interface(self.iface, constants.NETWORK_TYPE_MGMT) clhost_network, clhost_address = self._create_address_for_interface(self.iface, constants.NETWORK_TYPE_CLUSTER_HOST) self._do_update_context() configs = interface.get_interface_network_configs( self.context, self.iface) ipv6_autocnf_off = self._get_ipv6_autoconf_off(self.port['name']) options = {'post-up': '/usr/local/bin/tc_setup.sh eth0 mgmt 10000 > /dev/null; ' + '{}'.format(ipv6_autocnf_off), 'pre-up': 'sysctl -wq net.ipv6.conf.{}.accept_dad=0'.format(self.port['name']), 'mtu': '1500', 'stx-description': 'ifname:mgmt0,net:None'} expected = self._get_network_config_ifupdown( method='manual', ifname=f"{self.port['name']}", options=options) self.assertEqual(expected, configs[0]) configs = interface.get_interface_network_configs( self.context, self.iface, mgmt_network) ipv6_autocnf_off = self._get_ipv6_autoconf_off(self.port['name']) options = {'post-up': '%s' % ipv6_autocnf_off, 'mtu': '1500', 'stx-description': 'ifname:mgmt0,net:mgmt', 'gateway': '192.168.204.1'} expected = self._get_static_network_config_ifupdown( ipaddress='192.168.204.10', ifname=f"{self.port['name']}:{mgmt_network.id}-{mgmt_address.id}", options=options) self.assertEqual(expected, configs[0]) configs = interface.get_interface_network_configs( self.context, self.iface, clhost_network) ipv6_autocnf_off = self._get_ipv6_autoconf_off(self.port['name']) options = {'post-up': '%s' % ipv6_autocnf_off, 'mtu': '1500', 'stx-description': 'ifname:mgmt0,net:cluster-host', 'gateway': '192.168.206.1'} expected = self._get_static_network_config_ifupdown( ipaddress='192.168.206.10', ifname=f"{self.port['name']}:{clhost_network.id}-{clhost_address.id}", options=options) self.assertEqual(expected, configs[0]) def test_get_controller_vlan_config_over_bond_ifupdown(self): self._create_host(constants.CONTROLLER) bond = self._create_bond_test("bond0") vlan = self._create_vlan_test("vlan1", None, None, 1, bond) self._do_update_context() configs = interface.get_interface_network_configs(self.context, vlan) ipv6_autocnf_off = self._get_ipv6_autoconf_off("vlan#1") mtu = '1500' set_mtu = self._get_postup_mtu("vlan#1", mtu) options = {'stx-description': 'ifname:vlan1,net:None', 'post-down': 'ip link del vlan#1', 'mtu': mtu, 'pre-up': '/sbin/modprobe -q 8021q; ip link add link ' '{} name vlan#1 type vlan id 1'.format( bond['ifname']), 'post-up': '{} {}'.format(set_mtu, ipv6_autocnf_off), 'vlan-raw-device': '{}'.format(bond['ifname'])} expected = self._get_network_config_ifupdown( ifname="vlan#1", method='manual', options=options) self.assertEqual(expected, configs[0]) def test_get_worker_ethernet_config_mgmt_ifupdown(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT, personality=constants.WORKER) network, address = self._create_address_for_interface(self.iface) self._do_update_context() configs = interface.get_interface_network_configs( self.context, self.iface, network) ipv6_autocnf_off = self._get_ipv6_autoconf_off(self.port['name']) options = {'stx-description': 'ifname:mgmt0,net:mgmt', 'mtu': '1500', 'gateway': '192.168.204.2', 'post-up': '{}'.format(ipv6_autocnf_off)} expected = self._get_static_network_config_ifupdown( ipaddress='192.168.204.10', ifname=f"{self.port['name']}:{network.id}-{address.id}", options=options) self.assertEqual(expected, configs[0]) def test_get_worker_ethernet_config_cluster_host_ifupdown(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_CLUSTER_HOST, personality=constants.WORKER) network, address = self._create_address_for_interface(self.iface) self._do_update_context() configs = interface.get_interface_network_configs( self.context, self.iface, network) ipv6_autocnf_off = self._get_ipv6_autoconf_off(self.port['name']) options = {'stx-description': 'ifname:mgmt0,net:cluster-host', 'mtu': '1500', 'gateway': '192.168.206.1', 'post-up': '{}'.format(ipv6_autocnf_off)} expected = self._get_static_network_config_ifupdown( ipaddress='192.168.206.10', ifname=f"{self.port['name']}:{network.id}-{address.id}", options=options) self.assertEqual(expected, configs[0]) def test_get_worker_ethernet_config_pci_sriov_ifupdown(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV, personality=constants.WORKER) self._do_update_context() configs = interface.get_interface_network_configs( self.context, self.iface) ipv6_autocnf_off = self._get_ipv6_autoconf_off(self.port['name']) options = {'stx-description': 'ifname:mgmt0,net:None', 'mtu': '1500', 'pre-up': 'echo 0 > /sys/class/net/{}/device/sriov_numvfs;' ' echo 0 > /sys/class/net/{}/device/sriov_numvfs'.format( self.port['name'], self.port['name']), 'post-up': '{}'.format(ipv6_autocnf_off)} expected = self._get_network_config_ifupdown( ifname=self.port['name'], method='manual', options=options) self.assertEqual(expected, configs[0]) def test_get_worker_ethernet_config_pci_pthru_ifupdown(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PCI_PASSTHROUGH, constants.NETWORK_TYPE_PCI_PASSTHROUGH, personality=constants.WORKER) self._do_update_context() configs = interface.get_interface_network_configs( self.context, self.iface) ipv6_autocnf_off = self._get_ipv6_autoconf_off(self.port['name']) options = {'stx-description': 'ifname:mgmt0,net:None', 'mtu': '1500', 'pre-up': 'if [ -f /sys/class/net/{}/device/sriov_numvfs ];' ' then echo 0 > /sys/class/net/{}/device/sriov_numvfs; fi'.format( self.port['name'], self.port['name']), 'post-up': '{}'.format(ipv6_autocnf_off)} expected = self._get_network_config_ifupdown( ifname=self.port['name'], method='manual', options=options) self.assertEqual(expected, configs[0]) def test_get_worker_ethernet_config_pci_sriov_vf(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV, name='sriov1', sriov_numvfs=2) vf = self._create_vf_test("vf", 1, None, lower_iface=self.iface) self._do_update_context() configs = interface.get_interface_network_configs(self.context, vf) expected = [] self.assertEqual(expected, configs) def _create_sriov_vf_config(self, iface_vf_driver, port_vf_driver, vf_addr_list, num_vfs, max_tx_rate=None): self._create_host_and_interface( constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV, name='sriov1', iface_sriov_vf_driver=iface_vf_driver, sriov_numvfs=num_vfs, max_tx_rate=max_tx_rate, port_sriov_vf_driver=port_vf_driver, sriov_vfs_pci_address=vf_addr_list) self._do_update_context() config = interface.get_sriov_config(self.context, self.iface) return config def test_get_sriov_config_netdevice(self): vf_addr1 = "0000:81:00.0" vf_addr2 = "0000:81:01.0" device_id = '1572' port_name = 'eth0' vf_addr_list = "{},{}".format(vf_addr1, vf_addr2) num_vfs = 2 config = self._create_sriov_vf_config( constants.SRIOV_DRIVER_TYPE_NETDEVICE, 'i40evf', vf_addr_list, num_vfs) expected_vf_config = { '0000:81:00.0': {'addr': '0000:81:00.0', 'driver': 'i40evf'}, '0000:81:01.0': {'addr': '0000:81:01.0', 'driver': 'i40evf'} } expected = self._get_sriov_config( ifname=self.iface['ifname'], vf_driver='i40evf', num_vfs=num_vfs, device_id=device_id, port_name=port_name, vf_config=expected_vf_config,) self.assertEqual(expected, config) def test_get_sriov_config_vfio(self): vf_addr1 = "0000:81:00.0" vf_addr2 = "0000:81:01.0" device_id = '1572' port_name = 'eth0' vf_addr_list = "{},{}".format(vf_addr1, vf_addr2) num_vfs = 4 config = self._create_sriov_vf_config( constants.SRIOV_DRIVER_TYPE_VFIO, 'i40evf', vf_addr_list, num_vfs) expected_vf_config = { '0000:81:00.0': {'addr': '0000:81:00.0', 'driver': 'vfio-pci'}, '0000:81:01.0': {'addr': '0000:81:01.0', 'driver': 'vfio-pci'} } expected = self._get_sriov_config( ifname=self.iface['ifname'], vf_driver='vfio-pci', num_vfs=num_vfs, device_id=device_id, port_name=port_name, vf_config=expected_vf_config) self.assertEqual(expected, config) def test_get_sriov_config_default(self): vf_addr1 = "0000:81:00.0" vf_addr2 = "0000:81:01.0" device_id = '1572' port_name = 'eth0' vf_addr_list = "{},{}".format(vf_addr1, vf_addr2) num_vfs = 1 config = self._create_sriov_vf_config( None, 'i40evf', vf_addr_list, num_vfs) expected_vf_config = { '0000:81:00.0': {'addr': '0000:81:00.0', 'driver': None}, '0000:81:01.0': {'addr': '0000:81:01.0', 'driver': None} } expected = self._get_sriov_config( ifname=self.iface['ifname'], vf_driver=None, device_id=device_id, port_name=port_name, num_vfs=num_vfs, vf_config=expected_vf_config) self.assertEqual(expected, config) def test_get_sriov_config_iftype_vf(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV, name='sriov1', sriov_numvfs=4, iface_sriov_vf_driver=None, port_sriov_vf_driver="iavf", sriov_vfs_pci_address="0000:b1:02.0,0000:b1:02.1,0000:b1:02.2,0000:b1:02.3") self._create_vf_test("vf1", 1, 'vfio', lower_iface=self.iface) self._do_update_context() config = interface.get_sriov_config(self.context, self.iface) expected_vf_config = { '0000:b1:02.0': {'addr': '0000:b1:02.0', 'driver': None}, '0000:b1:02.1': {'addr': '0000:b1:02.1', 'driver': None}, '0000:b1:02.2': {'addr': '0000:b1:02.2', 'driver': None}, '0000:b1:02.3': {'addr': '0000:b1:02.3', 'driver': 'vfio-pci'} } expected = self._get_sriov_config( self.iface['ifname'], None, num_vfs=4, pf_addr=self.port['pciaddr'], port_name="eth0", vf_config=expected_vf_config) self.assertEqual(expected, config) def test_get_sriov_config_iftype_vf_nested(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV, name='sriov1', sriov_numvfs=4, iface_sriov_vf_driver=None, port_sriov_vf_driver="iavf", sriov_vfs_pci_address="0000:b1:02.0,0000:b1:02.1,0000:b1:02.2,0000:b1:02.3") vf1 = self._create_vf_test("vf1", 2, 'vfio', lower_iface=self.iface) self._create_vf_test("vf2", 1, 'netdevice', lower_iface=vf1) self._do_update_context() config = interface.get_sriov_config(self.context, self.iface) expected_vf_config = { '0000:b1:02.0': {'addr': '0000:b1:02.0', 'driver': None}, '0000:b1:02.1': {'addr': '0000:b1:02.1', 'driver': None}, '0000:b1:02.2': {'addr': '0000:b1:02.2', 'driver': 'vfio-pci'}, '0000:b1:02.3': {'addr': '0000:b1:02.3', 'driver': 'iavf'} } expected = self._get_sriov_config( self.iface['ifname'], None, num_vfs=4, pf_addr=self.port['pciaddr'], port_name="eth0", vf_config=expected_vf_config) self.assertEqual(expected, config) def test_get_sriov_config_iftype_vf_sibling(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV, name='sriov1', sriov_numvfs=4, iface_sriov_vf_driver=None, port_sriov_vf_driver="iavf", sriov_vfs_pci_address="0000:b1:02.0,0000:b1:02.1,0000:b1:02.2,0000:b1:02.3") self._create_vf_test("vf1", 2, 'vfio', lower_iface=self.iface) self._create_vf_test("vf2", 1, 'netdevice', lower_iface=self.iface) self._do_update_context() config = interface.get_sriov_config(self.context, self.iface) expected_vf_config = { '0000:b1:02.0': {'addr': '0000:b1:02.0', 'driver': None}, '0000:b1:02.1': {'addr': '0000:b1:02.1', 'driver': 'iavf'}, '0000:b1:02.2': {'addr': '0000:b1:02.2', 'driver': 'vfio-pci'}, '0000:b1:02.3': {'addr': '0000:b1:02.3', 'driver': 'vfio-pci'} } expected = self._get_sriov_config( self.iface['ifname'], None, num_vfs=4, pf_addr=self.port['pciaddr'], port_name="eth0", vf_config=expected_vf_config) self.assertEqual(expected, config) @mock.patch.object(utils, 'get_sriov_vf_index') def test_get_sriov_config_with_ratelimit(self, mock_get_sriov_vf_index): vf_addr1 = "0000:81:00.0" vf_addr2 = "0000:81:01.0" device_id = '1572' port_name = 'eth0' vf_addr_list = "{},{}".format(vf_addr1, vf_addr2) num_vfs = 4 max_tx_rate = 1000 mock_get_sriov_vf_index.side_effect = [0, 1] config = self._create_sriov_vf_config( constants.SRIOV_DRIVER_TYPE_VFIO, 'i40evf', vf_addr_list, num_vfs, max_tx_rate) expected_vf_config = { '0000:81:00.0': {'addr': '0000:81:00.0', 'driver': 'vfio-pci', 'max_tx_rate': 1000, 'vfnumber': 0}, '0000:81:01.0': {'addr': '0000:81:01.0', 'driver': 'vfio-pci', 'max_tx_rate': 1000, 'vfnumber': 1} } expected = self._get_sriov_config( ifname=self.iface['ifname'], vf_driver='vfio-pci', num_vfs=num_vfs, device_id=device_id, port_name=port_name, vf_config=expected_vf_config) self.assertEqual(expected, config) def test_get_sriov_config_vf_sibling_with_ratelimit(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV, name='sriov1', sriov_numvfs=4, iface_sriov_vf_driver=None, port_sriov_vf_driver="iavf", sriov_vfs_pci_address="0000:b1:02.0,0000:b1:02.1,0000:b1:02.2,0000:b1:02.3") self._create_vf_test("vf1", 2, 'vfio', lower_iface=self.iface) self._create_vf_test("vf2", 1, 'netdevice', lower_iface=self.iface, max_tx_rate=1000) self._do_update_context() config = interface.get_sriov_config(self.context, self.iface) expected_vf_config = { '0000:b1:02.0': {'addr': '0000:b1:02.0', 'driver': None}, '0000:b1:02.1': {'addr': '0000:b1:02.1', 'driver': 'iavf', 'max_tx_rate': 1000, 'vfnumber': 1}, '0000:b1:02.2': {'addr': '0000:b1:02.2', 'driver': 'vfio-pci'}, '0000:b1:02.3': {'addr': '0000:b1:02.3', 'driver': 'vfio-pci'} } expected = self._get_sriov_config( self.iface['ifname'], None, num_vfs=4, pf_addr=self.port['pciaddr'], port_name="eth0", vf_config=expected_vf_config) self.assertEqual(expected, config) def test_get_fpga_config(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV, name='n3000', sriov_numvfs=4, iface_sriov_vf_driver=None, port_sriov_vf_driver="iavf", sriov_vfs_pci_address="0000:b1:02.0,0000:b1:02.1,0000:b1:02.2,0000:b1:02.3", pdevice="Ethernet Controller [0d58]") self._create_vf_test("vf1", 2, 'vfio', lower_iface=self.iface) self._create_vlan_test('oam', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_OAM, 1, lower_iface=self.iface) self._do_update_context() config = interface.get_fpga_config(self.context, self.iface) # Since the interface's fpga config is used to determine whether # any upper vlan interfaces need to be brought up after an # n3000 device is reset, we ensure that no virtual (VF) # type interfaces are in the dict. expected = self._get_fpga_config( portname='eth0', device_id='0d58', vlans=["vlan1"]) self.assertEqual(expected, config) def test_is_an_n3000_i40_device_true(self): self._create_host_and_interface( constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT, pdevice="Ethernet Controller [0d58]") self._do_update_context() self.assertTrue( interface.is_an_n3000_i40_device(self.context, self.iface)) def test_find_sriov_interfaces_by_driver_one(self): self._create_host(constants.CONTROLLER) expected = ['sriov_cx4_0'] vf_num = 2 for ifname in expected: self._create_sriov_cx4_if_test(ifname, vf_num) self._do_update_context() ifaces = interface.find_sriov_interfaces_by_driver( self.context, constants.DRIVER_MLX_CX4) results = [iface['ifname'] for iface in ifaces] self.assertEqual(sorted(results), sorted(expected)) def test_find_sriov_interfaces_by_driver_two(self): self._create_host(constants.CONTROLLER) expected = ['sriov_cx4_0', 'sriov_cx4_1'] vf_num = 2 for ifname in expected: self._create_sriov_cx4_if_test(ifname, vf_num) self._do_update_context() ifaces = interface.find_sriov_interfaces_by_driver( self.context, constants.DRIVER_MLX_CX4) results = [iface['ifname'] for iface in ifaces] self.assertEqual(sorted(results), sorted(expected)) def _create_sriov_cx4_if_test(self, name, vf_num, **kwargs): port, iface = self._create_ethernet_test( name, constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV, driver=constants.DRIVER_MLX_CX4, sriov_numvfs=vf_num, **kwargs) return port, iface class InterfaceHostTestCase(InterfaceTestCaseMixin, dbbase.BaseHostTestCase): def setUp(self): super(InterfaceHostTestCase, self).setUp() self._setup_context() self.expected_platform_interfaces = [] self.expected_data_interfaces = [] self.expected_pci_interfaces = [] self.expected_slow_interfaces = [] self.expected_bridged_interfaces = [] self.expected_slave_interfaces = [] self.expected_mlx_interfaces = [] self.expected_bmc_interface = None self._assign_addresses_to_pool() self.exp_yaml_config = {} def _setup_configuration(self): # Personality is set to worker to avoid issues due to missing OAM # interface in this empty/dummy configuration self.host = self._create_test_host(constants.WORKER) def _update_context(self): # ensure DB entries are updated prior to updating the context which # will re-read the entries from the DB. self.host.save(self.admin_context) super(InterfaceHostTestCase, self)._update_context() def _create_hieradata_directory(self): hiera_path = os.path.join(os.environ['VIRTUAL_ENV'], 'hieradata') if not os.path.exists(hiera_path): os.mkdir(hiera_path, 0o755) return hiera_path def _get_config_filename(self, hiera_directory): class_name = self.__class__.__name__ return os.path.join(hiera_directory, class_name) + ".yaml" def test_generate_interface_config_ifupdown(self): hieradata_directory = self._create_hieradata_directory() config_filename = self._get_config_filename(hieradata_directory) with open(config_filename, 'w') as config_file: config = self.operator.interface.get_host_config(self.host) # pylint: disable=no-member self.assertIsNotNone(config) yaml.dump(config, config_file, default_flow_style=False) def test_interface_config_yaml_data_validation(self): hieradata_directory = self._create_hieradata_directory() config_filename = self._get_config_filename(hieradata_directory) with open(config_filename, 'w') as config_file: config = self.operator.interface.get_host_config(self.host) # pylint: disable=no-member self.assertIsNotNone(config) yaml.dump(config, config_file, default_flow_style=False) hiera_data = dict() with open(config_filename, 'r') as config_file: hiera_data = yaml.safe_load(config_file) self.assertTrue('platform::network::interfaces::network_config' in hiera_data.keys()) if len(self.exp_yaml_config): intf_cfg = hiera_data['platform::network::interfaces::network_config'] for exp_intf in self.exp_yaml_config: self.assertTrue(exp_intf in intf_cfg.keys()) if exp_intf != 'lo': self.assertEqual(self.exp_yaml_config[exp_intf]['family'], intf_cfg[exp_intf]['family']) self.assertEqual(self.exp_yaml_config[exp_intf]['method'], intf_cfg[exp_intf]['method']) self.assertEqual(self.exp_yaml_config[exp_intf]['stx-description'], intf_cfg[exp_intf]['options']['stx-description']) if self.exp_yaml_config[exp_intf]['tc']: self.assertTrue('tc_setup.sh' in intf_cfg[exp_intf]['options']['post-up']) else: if 'post-up' in intf_cfg[exp_intf]['options'].keys(): self.assertFalse('tc_setup.sh' in intf_cfg[exp_intf]['options']['post-up']) def test_create_interface_context(self): context = self.operator.interface._create_interface_context(self.host) # pylint: disable=no-member self.assertIn('personality', context) self.assertIn('subfunctions', context) self.assertIn('devices', context) self.assertIn('ports', context) self.assertIn('interfaces', context) self.assertIn('addresses', context) self.assertIn('routes', context) def test_is_platform_interface(self): if not self.expected_platform_interfaces: self.assertTrue(True) return for iface in self.interfaces: expected = bool(iface['ifname'] in self.expected_platform_interfaces) if interface.is_platform_interface(self.context, iface) != expected: print("iface %s is %sa kernel interface" % ( iface['ifname'], ('not ' if expected else ''))) self.assertFalse(True) def test_is_data_interface(self): if not self.expected_data_interfaces: self.assertTrue(True) return for iface in self.interfaces: expected = bool(iface['ifname'] in self.expected_data_interfaces) if interface.is_data_interface(self.context, iface) != expected: print("iface %s is %sa data interface" % ( iface['ifname'], ('not ' if expected else ''))) self.assertFalse(True) def test_is_pci_interface(self): if not self.expected_pci_interfaces: self.assertTrue(True) return for iface in self.interfaces: expected = bool(iface['ifname'] in self.expected_pci_interfaces) if interface.is_pci_interface(iface) != expected: print("iface %s is %sa pci interface" % ( iface['ifname'], ('not ' if expected else ''))) self.assertFalse(True) def test_is_a_mellanox_device(self): if not self.expected_mlx_interfaces: self.assertTrue(True) return for iface in self.interfaces: if (iface['iftype'] not in [constants.INTERFACE_TYPE_ETHERNET, constants.INTERFACE_TYPE_VF]): continue expected = bool(iface['ifname'] in self.expected_mlx_interfaces) if interface.is_a_mellanox_device(self.context, iface) != expected: print("iface %s is %sa mellanox device" % ( iface['ifname'], ('not ' if expected else ''))) self.assertFalse(True) def test_is_dpdk_compatible_false(self): if not self.expected_slow_interfaces: self.assertTrue(True) return for iface in self.interfaces: expected = bool(iface['ifname'] in self.expected_slow_interfaces) if interface.is_dpdk_compatible(self.context, iface) == expected: print("iface %s is %sdpdk compatible" % ( iface['ifname'], ('not ' if not expected else ''))) self.assertFalse(True) def test_is_bridged_interface(self): if not self.expected_bridged_interfaces: self.assertTrue(True) return for iface in self.interfaces: expected = bool( iface['ifname'] in self.expected_bridged_interfaces) if interface.is_bridged_interface(self.context, iface) != expected: print("iface %s is %sa bridged interface" % ( iface['ifname'], ('not ' if expected else ''))) self.assertFalse(True) def test_is_slave_interface(self): if not self.expected_slave_interfaces: self.assertTrue(True) return for iface in self.interfaces: expected = bool(iface['ifname'] in self.expected_slave_interfaces) if interface.is_slave_interface(self.context, iface) != expected: print("iface %s is %sa slave interface" % ( iface['ifname'], ('not ' if expected else ''))) self.assertFalse(True) def test_needs_interface_config(self): expected_configured = (self.expected_platform_interfaces + [self.expected_bmc_interface]) if interface.is_worker_subfunction(self.context): expected_configured += (self.expected_pci_interfaces + self.expected_slow_interfaces + self.expected_mlx_interfaces) if (expected_configured == [None]): self.assertTrue(True) return for iface in self.interfaces: expected = bool(iface['ifname'] in expected_configured) actual = interface.needs_interface_config(self.context, iface) if expected != actual: print("iface %s is %sconfigured" % ( iface['ifname'], ('not ' if expected else ''))) self.assertFalse(True) class InterfaceControllerEthernet(InterfaceHostTestCase): def _setup_configuration(self): # Setup a sample configuration where all platform interfaces are # ethernet interfaces. self.host = self._create_test_host(constants.CONTROLLER) self._create_ethernet_test('oam', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_OAM, hostname=self.host.hostname) self._create_ethernet_test('mgmt', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT, hostname=self.host.hostname) self._create_ethernet_test('cluster-host', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_CLUSTER_HOST, hostname=self.host.hostname) self._create_ethernet_test('none') def setUp(self): super(InterfaceControllerEthernet, self).setUp() self.expected_bmc_interface = 'mgmt' self.expected_platform_interfaces = ['oam', 'mgmt', 'cluster-host'] self.exp_yaml_config = { "eth0": {'family': 'inet', 'method': 'static', 'stx-description': f'ifname:oam,net:{constants.NETWORK_TYPE_OAM}', 'tc': False}, "eth1": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:mgmt,net:{None}', 'tc': True}, "eth1:1-3": {'family': 'inet', 'method': 'static', 'stx-description': f'ifname:mgmt,net:{constants.NETWORK_TYPE_PXEBOOT}', 'tc': False}, "eth1:2-7": {'family': 'inet', 'method': 'static', 'stx-description': f'ifname:mgmt,net:{constants.NETWORK_TYPE_MGMT}', 'tc': False}, "eth2": {'family': 'inet', 'method': 'static', 'stx-description': 'ifname:cluster-host,' f'net:{constants.NETWORK_TYPE_CLUSTER_HOST}', 'tc': False}, "lo": {'family': 'inet', 'method': 'loopback', 'stx-description': '', 'tc': False}, } class InterfaceControllerEthernetCfg2(InterfaceHostTestCase): def _setup_configuration(self): # Setup a sample configuration where all platform interfaces are # ethernet interfaces. In this case the management is assigned # to management and cluster-host networks self.host = self._create_test_host(constants.CONTROLLER) self._create_ethernet_test('oam0', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_OAM, hostname=self.host.hostname) self._create_ethernet_test('mgmt0', constants.INTERFACE_CLASS_PLATFORM, [constants.NETWORK_TYPE_MGMT, constants.NETWORK_TYPE_CLUSTER_HOST], hostname=self.host.hostname) self._create_ethernet_test('none') def setUp(self): super(InterfaceControllerEthernetCfg2, self).setUp() self.expected_bmc_interface = 'mgmt0' self.expected_platform_interfaces = ['oam0', 'mgmt0'] self.exp_yaml_config = { "eth0": {'family': 'inet', 'method': 'static', 'stx-description': f'ifname:oam0,net:{constants.NETWORK_TYPE_OAM}', 'tc': False}, "eth1": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:mgmt0,net:{None}', 'tc': True}, "eth1:1-3": {'family': 'inet', 'method': 'static', 'stx-description': f'ifname:mgmt0,net:{constants.NETWORK_TYPE_PXEBOOT}', 'tc': False}, "eth1:2-7": {'family': 'inet', 'method': 'static', 'stx-description': f'ifname:mgmt0,net:{constants.NETWORK_TYPE_MGMT}', 'tc': False}, "eth1:4-15": {'family': 'inet', 'method': 'static', 'stx-description': 'ifname:mgmt0,' f'net:{constants.NETWORK_TYPE_CLUSTER_HOST}', 'tc': False}, "lo": {'family': 'inet', 'method': 'loopback', 'stx-description': '', 'tc': False}, } class InterfaceControllerEthernetCfg3(InterfaceHostTestCase): def _setup_configuration(self): # Setup a sample configuration where all platform interfaces are # ethernet interfaces. In this case the management is assigned # to management, pxeboot and cluster-host networks self.host = self._create_test_host(constants.CONTROLLER) self._create_ethernet_test('oam0', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_OAM, hostname=self.host.hostname) self._create_ethernet_test('mgmt0', constants.INTERFACE_CLASS_PLATFORM, [constants.NETWORK_TYPE_MGMT, constants.NETWORK_TYPE_CLUSTER_HOST, constants.NETWORK_TYPE_PXEBOOT], hostname=self.host.hostname) self._create_ethernet_test('none') def setUp(self): super(InterfaceControllerEthernetCfg3, self).setUp() self.expected_bmc_interface = 'mgmt0' self.expected_platform_interfaces = ['oam0', 'mgmt0'] self.exp_yaml_config = { "eth0": {'family': 'inet', 'method': 'static', 'stx-description': f'ifname:oam0,net:{constants.NETWORK_TYPE_OAM}', 'tc': False}, "eth1": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:mgmt0,net:{None}', 'tc': True}, "eth1:1-3": {'family': 'inet', 'method': 'static', 'stx-description': f'ifname:mgmt0,net:{constants.NETWORK_TYPE_PXEBOOT}', 'tc': False}, "eth1:2-7": {'family': 'inet', 'method': 'static', 'stx-description': f'ifname:mgmt0,net:{constants.NETWORK_TYPE_MGMT}', 'tc': False}, "eth1:4-15": {'family': 'inet', 'method': 'static', 'stx-description': 'ifname:mgmt0,' f'net:{constants.NETWORK_TYPE_CLUSTER_HOST}', 'tc': False}, "lo": {'family': 'inet', 'method': 'loopback', 'stx-description': '', 'tc': False}, } class InterfaceControllerBond(InterfaceHostTestCase): def _setup_configuration(self): # Setup a sample configuration where all platform interfaces are # aggregated ethernet interfaces. self.host = self._create_test_host(constants.CONTROLLER) self._create_bond_test('oam0', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_OAM, hostname=self.host.hostname) self._create_bond_test('mgmt0', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT, hostname=self.host.hostname) self._create_bond_test('cluster-host0', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_CLUSTER_HOST, hostname=self.host.hostname) def setUp(self): super(InterfaceControllerBond, self).setUp() self.expected_bmc_interface = 'mgmt' self.expected_platform_interfaces = ['eth0', 'eth1', 'oam0', 'eth3', 'eth4', 'mgmt0', 'eth6', 'eth7', 'cluster-host0'] self.expected_slave_interfaces = ['eth0', 'eth1', 'eth3', 'eth4', 'eth6', 'eth7'] # the slave interfaces do not match the linux name created by the test database # port:eth0 => ifname:eth0, port:eth1 => ifname:eth1 # port:eth2 => ifname:eth3, port:eth3 => ifname:eth4 (differ) # port:eth4 => ifname:eth6, port:eth5 => ifname:eth7 (differ) self.exp_yaml_config = { "eth0": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:eth0,net:{None}', 'tc': False}, "eth1": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:eth1,net:{None}', 'tc': False}, "eth2": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:eth3,net:{None}', 'tc': False}, "eth3": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:eth4,net:{None}', 'tc': False}, "eth4": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:eth6,net:{None}', 'tc': False}, "eth5": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:eth7,net:{None}', 'tc': False}, "oam0": {'family': 'inet', 'method': 'static', 'stx-description': f'ifname:oam0,net:{constants.NETWORK_TYPE_OAM}', 'tc': False}, "mgmt0": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:mgmt0,net:{None}', 'tc': True}, "mgmt0:1-3": {'family': 'inet', 'method': 'static', 'stx-description': f'ifname:mgmt0,net:{constants.NETWORK_TYPE_PXEBOOT}', 'tc': False}, "mgmt0:2-7": {'family': 'inet', 'method': 'static', 'stx-description': f'ifname:mgmt0,net:{constants.NETWORK_TYPE_MGMT}', 'tc': False}, "cluster-host0": {'family': 'inet', 'method': 'static', 'stx-description': 'ifname:cluster-host0,' f'net:{constants.NETWORK_TYPE_CLUSTER_HOST}', 'tc': False}, "lo": {'family': 'inet', 'method': 'loopback', 'stx-description': '', 'tc': False}, } class InterfaceControllerVlanOverBond(InterfaceHostTestCase): def _setup_configuration(self): # Setup a sample configuration where all platform interfaces are # vlan interfaces over aggregated ethernet interfaces self.host = self._create_test_host(constants.CONTROLLER) bond = self._create_bond_test('pxeboot0', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_PXEBOOT, hostname=self.host.hostname) self._create_vlan_test('oam0', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_OAM, 1, bond, hostname=self.host.hostname) self._create_vlan_test('mgmt0', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT, 2, bond, hostname=self.host.hostname) self._create_vlan_test('cluster-host0', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_CLUSTER_HOST, 3, bond, hostname=self.host.hostname) self._create_ethernet_test('none') def setUp(self): super(InterfaceControllerVlanOverBond, self).setUp() self.expected_bmc_interface = 'pxeboot' self.expected_platform_interfaces = ['eth0', 'eth1', 'pxeboot0', 'oam0', 'mgmt0', 'cluster-host0'] self.expected_slave_interfaces = ['eth0', 'eth1'] self.exp_yaml_config = { "eth0": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:eth0,net:{None}', 'tc': False}, "eth1": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:eth1,net:{None}', 'tc': False}, "pxeboot0": {'family': 'inet', 'method': 'static', 'stx-description': f'ifname:pxeboot0,net:{constants.NETWORK_TYPE_PXEBOOT}', 'tc': False}, "vlan1": {'family': 'inet', 'method': 'static', 'stx-description': f'ifname:oam0,net:{constants.NETWORK_TYPE_OAM}', 'tc': False}, "vlan2": {'family': 'inet', 'method': 'static', 'stx-description': f'ifname:mgmt0,net:{constants.NETWORK_TYPE_MGMT}', 'tc': True}, "vlan3": {'family': 'inet', 'method': 'static', 'stx-description': 'ifname:cluster-host0,' f'net:{constants.NETWORK_TYPE_CLUSTER_HOST}', 'tc': False}, "lo": {'family': 'inet', 'method': 'loopback', 'stx-description': '', 'tc': False}, } class InterfaceControllerVlanOverEthernet(InterfaceHostTestCase): def _setup_configuration(self): # Setup a sample configuration where all platform interfaces are # vlan interfaces over ethernet interfaces self.host = self._create_test_host(constants.CONTROLLER) port, iface = self._create_ethernet_test( 'pxeboot', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_PXEBOOT, hostname=self.host.hostname) self._create_vlan_test('oam', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_OAM, 1, iface, hostname=self.host.hostname) self._create_vlan_test('mgmt', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT, 2, iface, hostname=self.host.hostname) self._create_vlan_test('cluster-host', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_CLUSTER_HOST, 3, iface, hostname=self.host.hostname) self._create_ethernet_test('none') def setUp(self): super(InterfaceControllerVlanOverEthernet, self).setUp() self.expected_bmc_interface = 'pxeboot' self.expected_platform_interfaces = ['eth0', 'pxeboot', 'oam', 'mgmt', 'cluster-host'] class InterfaceComputeEthernet(InterfaceHostTestCase): def _setup_configuration(self): # Setup a sample configuration where the personality is set to a # worker and all interfaces are ethernet interfaces. Do not explicit # attach the PXEboot network self.host = self._create_test_host(constants.WORKER) _, if_mgmt = self._create_ethernet_test('mgmt', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT, hostname=self.host.hostname) _, if_clhost = self._create_ethernet_test('cluster-host', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_CLUSTER_HOST, hostname=self.host.hostname) self._create_ethernet_test('data', constants.INTERFACE_CLASS_DATA, hostname=self.host.hostname) self._create_ethernet_test('sriov', constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV, hostname=self.host.hostname) self._create_ethernet_test('pthru', constants.INTERFACE_CLASS_PCI_PASSTHROUGH, constants.NETWORK_TYPE_PCI_PASSTHROUGH, hostname=self.host.hostname) self._create_ethernet_test('slow', constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA, dpdksupport=False, hostname=self.host.hostname) self._create_ethernet_test('mlx5', constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA, driver=constants.DRIVER_MLX_CX4, hostname=self.host.hostname) self._create_ethernet_test('none') self._create_address_for_interface(if_mgmt) self._create_address_for_interface(if_clhost) def setUp(self): super(InterfaceComputeEthernet, self).setUp() self.expected_bmc_interface = 'mgmt' self.expected_platform_interfaces = ['mgmt', 'cluster-host'] self.expected_data_interfaces = ['slow', 'data', 'mlx5'] self.expected_pci_interfaces = ['sriov', 'pthru'] self.expected_slow_interfaces = ['slow'] self.expected_bridged_interfaces = ['slow'] self.expected_slave_interfaces = [] self.expected_mlx_interfaces = ['mlx5'] self.exp_yaml_config = { "eth0": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:mgmt,net:{None}', 'tc': True}, "eth0:1-0": {'family': 'inet', 'method': 'dhcp', 'stx-description': f'ifname:mgmt,net:{constants.NETWORK_TYPE_PXEBOOT}', 'tc': False}, "eth0:2-37": {'family': 'inet', 'method': 'static', 'stx-description': f'ifname:mgmt,net:{constants.NETWORK_TYPE_MGMT}', 'tc': False}, "eth1": {'family': 'inet', 'method': 'static', 'stx-description': f'ifname:cluster-host,' f'net:{constants.NETWORK_TYPE_CLUSTER_HOST}', 'tc': False}, "eth3": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:sriov,net:{None}', 'tc': False}, "eth4": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:pthru,net:{None}', 'tc': False}, "eth5": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:slow,net:{None}', 'tc': False}, "eth6": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:mlx5,net:{None}', 'tc': False}, "lo": {'family': 'inet', 'method': 'loopback', 'stx-description': '', 'tc': False}, } class InterfaceComputeEthernetCfg2(InterfaceHostTestCase): def _setup_configuration(self): # Setup a sample configuration where the personality is set to a # worker and all interfaces are ethernet interfaces. # Explicitly assign PXEboot network with the management network self.host = self._create_test_host(constants.WORKER) _, if_mgmt = self._create_ethernet_test('mgmt', constants.INTERFACE_CLASS_PLATFORM, [constants.NETWORK_TYPE_MGMT, constants.NETWORK_TYPE_PXEBOOT], hostname=self.host.hostname) _, if_clhost = self._create_ethernet_test('cluster-host', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_CLUSTER_HOST, hostname=self.host.hostname) self._create_ethernet_test('data', constants.INTERFACE_CLASS_DATA, hostname=self.host.hostname) self._create_ethernet_test('sriov', constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV, hostname=self.host.hostname) self._create_ethernet_test('pthru', constants.INTERFACE_CLASS_PCI_PASSTHROUGH, constants.NETWORK_TYPE_PCI_PASSTHROUGH, hostname=self.host.hostname) self._create_ethernet_test('slow', constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA, dpdksupport=False, hostname=self.host.hostname) self._create_ethernet_test('mlx5', constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA, driver=constants.DRIVER_MLX_CX4, hostname=self.host.hostname) self._create_ethernet_test('none') self._create_address_for_interface(if_mgmt) self._create_address_for_interface(if_clhost) def setUp(self): super(InterfaceComputeEthernetCfg2, self).setUp() self.expected_bmc_interface = 'mgmt' self.expected_platform_interfaces = ['mgmt', 'cluster-host'] self.expected_data_interfaces = ['slow', 'data', 'mlx5'] self.expected_pci_interfaces = ['sriov', 'pthru'] self.expected_slow_interfaces = ['slow'] self.expected_bridged_interfaces = ['slow'] self.expected_slave_interfaces = [] self.expected_mlx_interfaces = ['mlx5'] self.exp_yaml_config = { "eth0": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:mgmt,net:{None}', 'tc': True}, "eth0:1-0": {'family': 'inet', 'method': 'dhcp', 'stx-description': f'ifname:mgmt,net:{constants.NETWORK_TYPE_PXEBOOT}', 'tc': False}, "eth0:2-37": {'family': 'inet', 'method': 'static', 'stx-description': f'ifname:mgmt,net:{constants.NETWORK_TYPE_MGMT}', 'tc': False}, "eth1": {'family': 'inet', 'method': 'static', 'stx-description': f'ifname:cluster-host,' f'net:{constants.NETWORK_TYPE_CLUSTER_HOST}', 'tc': False}, "eth3": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:sriov,net:{None}', 'tc': False}, "eth4": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:pthru,net:{None}', 'tc': False}, "eth5": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:slow,net:{None}', 'tc': False}, "eth6": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:mlx5,net:{None}', 'tc': False}, "lo": {'family': 'inet', 'method': 'loopback', 'stx-description': '', 'tc': False}, } class InterfaceComputeEthernetCfg3(InterfaceHostTestCase): def _setup_configuration(self): # Setup a sample configuration where the personality is set to a # worker and all interfaces are ethernet interfaces. # explicitly assign pxeboot network with the cluster-host network self.host = self._create_test_host(constants.WORKER) _, if_mgmt = self._create_ethernet_test('mgmt', constants.INTERFACE_CLASS_PLATFORM, [constants.NETWORK_TYPE_MGMT], hostname=self.host.hostname) _, if_clhost = self._create_ethernet_test('cluster-host', constants.INTERFACE_CLASS_PLATFORM, [constants.NETWORK_TYPE_CLUSTER_HOST, constants.NETWORK_TYPE_PXEBOOT], hostname=self.host.hostname) self._create_ethernet_test('data', constants.INTERFACE_CLASS_DATA, hostname=self.host.hostname) self._create_ethernet_test('sriov', constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV, hostname=self.host.hostname) self._create_ethernet_test('pthru', constants.INTERFACE_CLASS_PCI_PASSTHROUGH, constants.NETWORK_TYPE_PCI_PASSTHROUGH, hostname=self.host.hostname) self._create_ethernet_test('slow', constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA, dpdksupport=False, hostname=self.host.hostname) self._create_ethernet_test('mlx5', constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA, driver=constants.DRIVER_MLX_CX4, hostname=self.host.hostname) self._create_ethernet_test('none') self._create_address_for_interface(if_mgmt) self._create_address_for_interface(if_clhost) def setUp(self): super(InterfaceComputeEthernetCfg3, self).setUp() self.expected_bmc_interface = 'mgmt' self.expected_platform_interfaces = ['mgmt', 'cluster-host'] self.expected_data_interfaces = ['slow', 'data', 'mlx5'] self.expected_pci_interfaces = ['sriov', 'pthru'] self.expected_slow_interfaces = ['slow'] self.expected_bridged_interfaces = ['slow'] self.expected_slave_interfaces = [] self.expected_mlx_interfaces = ['mlx5'] self.exp_yaml_config = { "eth0": {'family': 'inet', 'method': 'static', 'stx-description': f'ifname:mgmt,net:{constants.NETWORK_TYPE_MGMT}', 'tc': True}, "eth1": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:cluster-host,net:{None}', 'tc': False}, "eth1:1-0": {'family': 'inet', 'method': 'dhcp', 'stx-description': f'ifname:cluster-host,net:{constants.NETWORK_TYPE_PXEBOOT}', 'tc': False}, "eth1:4-38": {'family': 'inet', 'method': 'static', 'stx-description': f'ifname:cluster-host,' f'net:{constants.NETWORK_TYPE_CLUSTER_HOST}', 'tc': False}, "eth3": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:sriov,net:{None}', 'tc': False}, "eth4": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:pthru,net:{None}', 'tc': False}, "eth5": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:slow,net:{None}', 'tc': False}, "eth6": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:mlx5,net:{None}', 'tc': False}, "lo": {'family': 'inet', 'method': 'loopback', 'stx-description': '', 'tc': False}, } class InterfaceComputeVlanOverEthernet(InterfaceHostTestCase): def _setup_configuration(self): # Setup a sample configuration where the personality is set to a # worker and all interfaces are vlan interfaces over ethernet # interfaces. self.host = self._create_test_host(constants.WORKER) port, iface = self._create_ethernet_test( 'pxeboot', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_PXEBOOT) self._create_vlan_test('mgmt', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT, 2, iface) self._create_vlan_test('cluster-host', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_CLUSTER_HOST, 3) # since the system vswitch_type is ovs-dpdk, it will not generate config for 'data' self._create_vlan_test('data', constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA, 5) self._create_ethernet_test('sriov', constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV) self._create_ethernet_test('pthru', constants.INTERFACE_CLASS_PCI_PASSTHROUGH, constants.NETWORK_TYPE_PCI_PASSTHROUGH) def setUp(self): super(InterfaceComputeVlanOverEthernet, self).setUp() self.expected_bmc_interface = 'pxeboot' self.expected_platform_interfaces = ['pxeboot', 'mgmt', 'eth2', 'cluster-host'] self.expected_data_interfaces = ['eth4', 'data'] self.expected_pci_interfaces = ['sriov', 'pthru'] self.exp_yaml_config = { "eth0": {'family': 'inet', 'method': 'dhcp', 'stx-description': f'ifname:pxeboot,net:{constants.NETWORK_TYPE_PXEBOOT}', 'tc': False}, "eth1": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:eth2,net:{None}', 'tc': False}, "vlan2": {'family': 'inet', 'method': 'static', 'stx-description': f'ifname:mgmt,net:{constants.NETWORK_TYPE_MGMT}', 'tc': True}, "vlan3": {'family': 'inet', 'method': 'static', 'stx-description': f'ifname:cluster-host,' f'net:{constants.NETWORK_TYPE_CLUSTER_HOST}', 'tc': False}, "eth3": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:sriov,net:{None}', 'tc': False}, "eth4": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:pthru,net:{None}', 'tc': False}, "lo": {'family': 'inet', 'method': 'loopback', 'stx-description': '', 'tc': False}, } class InterfaceComputeVlanOverEthernetCfg2(InterfaceHostTestCase): def _setup_configuration(self): # Setup a sample configuration where the personality is set to a # worker and all interfaces are vlan interfaces over ethernet # interfaces, mgmt interface handles mgmt and cluster-hos networks self.host = self._create_test_host(constants.WORKER) system_dict = self.system.as_dict() system_dict['capabilities']['vswitch_type'] = constants.VSWITCH_TYPE_NONE dbutils.update_test_isystem(system_dict) port, iface = self._create_ethernet_test( 'pxeboot', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_PXEBOOT) if_mgmt = self._create_vlan_test('mgmt', constants.INTERFACE_CLASS_PLATFORM, [constants.NETWORK_TYPE_MGMT, constants.NETWORK_TYPE_CLUSTER_HOST], 2, iface) self._create_vlan_test('data', constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA, 5) self._create_ethernet_test('sriov', constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV) self._create_ethernet_test('pthru', constants.INTERFACE_CLASS_PCI_PASSTHROUGH, constants.NETWORK_TYPE_PCI_PASSTHROUGH) self._create_address_for_interface(if_mgmt, constants.NETWORK_TYPE_MGMT) self._create_address_for_interface(if_mgmt, constants.NETWORK_TYPE_CLUSTER_HOST) def setUp(self): super(InterfaceComputeVlanOverEthernetCfg2, self).setUp() self.exp_yaml_config = { "data": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:data,net:{None}', 'tc': False}, "eth0": {'family': 'inet', 'method': 'dhcp', 'stx-description': f'ifname:pxeboot,net:{constants.NETWORK_TYPE_PXEBOOT}', 'tc': False}, "eth1": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:eth2,net:{None}', 'tc': False}, "vlan2": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:mgmt,net:{None}', 'tc': True}, "vlan2:2-37": {'family': 'inet', 'method': 'static', 'stx-description': f'ifname:mgmt,net:{constants.NETWORK_TYPE_MGMT}', 'tc': False}, "vlan2:4-38": {'family': 'inet', 'method': 'static', 'stx-description': f'ifname:mgmt,' f'net:{constants.NETWORK_TYPE_CLUSTER_HOST}', 'tc': False}, "eth2": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:sriov,net:{None}', 'tc': False}, "eth3": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:pthru,net:{None}', 'tc': False}, "lo": {'family': 'inet', 'method': 'loopback', 'stx-description': '', 'tc': False}, } class InterfaceComputeVfOverSriov(InterfaceHostTestCase): def _setup_configuration(self): # Setup a sample configuration where the personality is set to a # worker and all interfaces are ethernet interfaces, aside from # a VF interface over SR-IOV self.host = self._create_test_host(constants.WORKER) self._create_ethernet_test('mgmt', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT) self._create_ethernet_test('cluster-host', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_CLUSTER_HOST) self._create_ethernet_test('data', constants.INTERFACE_CLASS_DATA) port, iface = self._create_ethernet_test( 'sriov', constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV, sriov_numvfs=2, sriov_vf_driver=None) self._create_vf_test("vf", 1, None, lower_iface=iface) self._create_ethernet_test('pthru', constants.INTERFACE_CLASS_PCI_PASSTHROUGH, constants.NETWORK_TYPE_PCI_PASSTHROUGH) # Mellanox devices should be identified correctly whether they are # the SR-IOV interface or a VF interface on top of another. # Driver can also be a string of different comma separated driver # names, this also tests for that port, iface = self._create_ethernet_test( 'mlx5', constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV, sriov_numvfs=2, driver=('%s,%s' % (constants.DRIVER_MLX_CX4, constants.DRIVER_MLX_CX4))) self._create_vf_test('vf_mlx5', 1, None, lower_iface=iface) def setUp(self): super(InterfaceComputeVfOverSriov, self).setUp() self.expected_bmc_interface = 'pxeboot' self.expected_platform_interfaces = ['pxeboot', 'mgmt', 'eth2', 'cluster-host'] self.expected_data_interfaces = ['eth4', 'data'] self.expected_pci_interfaces = ['sriov', 'pthru', 'vf', 'mlx5', 'vf_mlx5'] self.expected_mlx_interfaces = ['mlx5', 'vf_mlx5'] class InterfaceComputeBond(InterfaceHostTestCase): def _setup_configuration(self): # Setup a sample configuration where the personality is set to a # worker and all interfaces are aggregated ethernet interfaces. self.host = self._create_test_host(constants.WORKER) if_mgmt = self._create_bond_test('mgmt', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT) if_clhost = self._create_bond_test('cluster-host', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_CLUSTER_HOST) self._create_bond_test('data', constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA) self._create_ethernet_test('sriov', constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV) self._create_ethernet_test('pthru', constants.INTERFACE_CLASS_PCI_PASSTHROUGH, constants.NETWORK_TYPE_PCI_PASSTHROUGH) self._create_address_for_interface(if_mgmt) self._create_address_for_interface(if_clhost) def setUp(self): super(InterfaceComputeBond, self).setUp() self.expected_bmc_interface = 'mgmt' self.expected_platform_interfaces = ['eth0', 'eth1', 'mgmt', 'eth3', 'eth4', 'cluster-host'] self.expected_data_interfaces = ['eth6', 'eth7', 'data', 'eth12', 'eth13', 'ex'] self.expected_pci_interfaces = ['sriov', 'pthru'] self.expected_slave_interfaces = ['eth0', 'eth1', 'eth3', 'eth4', 'eth6', 'eth7', 'eth9', 'eth10', 'eth12', 'eth13'] self.exp_yaml_config = { "eth0": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:eth0,net:{None}', 'tc': False}, "eth1": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:eth1,net:{None}', 'tc': False}, "mgmt": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:mgmt,net:{None}', 'tc': True}, "mgmt:1-0": {'family': 'inet', 'method': 'dhcp', 'stx-description': f'ifname:mgmt,net:{constants.NETWORK_TYPE_PXEBOOT}', 'tc': False}, "mgmt:2-37": {'family': 'inet', 'method': 'static', 'stx-description': f'ifname:mgmt,net:{constants.NETWORK_TYPE_MGMT}', 'tc': False}, "eth2": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:eth3,net:{None}', 'tc': False}, "eth3": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:eth4,net:{None}', 'tc': False}, "cluster-host": {'family': 'inet', 'method': 'static', 'stx-description': f'ifname:cluster-host,' f'net:{constants.NETWORK_TYPE_CLUSTER_HOST}', 'tc': False}, "eth6": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:sriov,net:{None}', 'tc': False}, "eth7": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:pthru,net:{None}', 'tc': False}, "lo": {'family': 'inet', 'method': 'loopback', 'stx-description': '', 'tc': False}, } class InterfaceComputeVlanOverBond(InterfaceHostTestCase): def _setup_configuration(self): # Setup a sample configuration where the personality is set to a # worker and all interfaces are vlan interfaces over ethernet # interfaces. self.host = self._create_test_host(constants.WORKER) bond = self._create_bond_test('pxeboot', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_PXEBOOT) self._create_vlan_test('oam', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_OAM, 1, bond) self._create_vlan_test('mgmt', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT, 2, bond) self._create_vlan_test('cluster-host', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_CLUSTER_HOST, 3, bond) bond2 = self._create_bond_test('bond2') self._create_vlan_test('data', constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA, 5, bond2) self._create_ethernet_test('sriov', constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV) self._create_ethernet_test('pthru', constants.INTERFACE_CLASS_PCI_PASSTHROUGH, constants.NETWORK_TYPE_PCI_PASSTHROUGH) def setUp(self): super(InterfaceComputeVlanOverBond, self).setUp() self.expected_platform_interfaces = ['eth0', 'eth1', 'pxeboot', 'oam', 'mgmt', 'cluster-host'] self.expected_data_interfaces = ['eth6', 'eth7', 'bond2', 'data', 'eth14', 'eth15'] self.expected_slave_interfaces = ['eth0', 'eth1', 'eth6', 'eth7', 'eth10', 'eth11'] self.expected_pci_interfaces = ['sriov', 'pthru'] self.exp_yaml_config = { "eth0": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:eth0,net:{None}', 'tc': False}, "eth1": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:eth1,net:{None}', 'tc': False}, "pxeboot": {'family': 'inet', 'method': 'dhcp', 'stx-description': f'ifname:pxeboot,net:{constants.NETWORK_TYPE_PXEBOOT}', 'tc': False}, "vlan1": {'family': 'inet', 'method': 'dhcp', 'stx-description': f'ifname:oam,net:{constants.NETWORK_TYPE_OAM}', 'tc': False}, "vlan2": {'family': 'inet', 'method': 'static', 'stx-description': f'ifname:mgmt,net:{constants.NETWORK_TYPE_MGMT}', 'tc': True}, "vlan3": {'family': 'inet', 'method': 'static', 'stx-description': f'ifname:cluster-host,' f'net:{constants.NETWORK_TYPE_CLUSTER_HOST}', 'tc': False}, "eth4": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:sriov,net:{None}', 'tc': False}, "eth5": {'family': 'inet', 'method': 'manual', 'stx-description': f'ifname:pthru,net:{None}', 'tc': False}, "lo": {'family': 'inet', 'method': 'loopback', 'stx-description': '', 'tc': False}, } class InterfaceCpeEthernet(InterfaceHostTestCase): def _setup_configuration(self): # Setup a sample configuration where the personality is set to a # controller with a controller subfunction and all interfaces are # ethernet interfaces. self.host = self._create_test_host(constants.CONTROLLER) self._create_ethernet_test('oam', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_OAM) self._create_ethernet_test('mgmt', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT) self._create_ethernet_test('cluster-host', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_CLUSTER_HOST) self._create_ethernet_test('data', constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA) self._create_ethernet_test('sriov', constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV) self._create_ethernet_test('pthru', constants.INTERFACE_CLASS_PCI_PASSTHROUGH, constants.NETWORK_TYPE_PCI_PASSTHROUGH) port, iface = ( self._create_ethernet_test('slow', constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA, dpdksupport=False)) port, iface = ( self._create_ethernet_test('mlx5', constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA, driver=constants.DRIVER_MLX_CX4)) self._create_ethernet_test('none') def setUp(self): super(InterfaceCpeEthernet, self).setUp() self.expected_bmc_interface = 'mgmt' self.expected_platform_interfaces = ['oam', 'mgmt', 'cluster-host'] self.expected_data_interfaces = ['slow', 'data', 'mlx5'] self.expected_pci_interfaces = ['sriov', 'pthru'] self.expected_slow_interfaces = ['slow'] self.expected_bridged_interfaces = ['slow'] self.expected_slave_interfaces = [] self.expected_mlx_interfaces = ['mlx5'] class InterfaceCpeVlanOverEthernet(InterfaceHostTestCase): def _setup_configuration(self): # Setup a sample configuration where the personality is set to a # controller with a controller subfunction and all interfaces are # vlan interfaces over ethernet interfaces. self.host = self._create_test_host(constants.CONTROLLER) port, iface = self._create_ethernet_test( 'pxeboot', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_PXEBOOT) self._create_vlan_test('oam', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_OAM, 1, iface) self._create_vlan_test('mgmt', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT, 2, iface) self._create_vlan_test('cluster-host', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_CLUSTER_HOST, 3) self._create_vlan_test('data', constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA, 5) self._create_ethernet_test('sriov', constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV) self._create_ethernet_test('pthru', constants.INTERFACE_CLASS_PCI_PASSTHROUGH, constants.NETWORK_TYPE_PCI_PASSTHROUGH) def setUp(self): super(InterfaceCpeVlanOverEthernet, self).setUp() self.expected_bmc_interface = 'pxeboot' self.expected_platform_interfaces = ['pxeboot', 'mgmt', 'oam', 'eth3', 'cluster-host'] self.expected_data_interfaces = ['eth5', 'data'] self.expected_pci_interfaces = ['sriov', 'pthru'] class InterfaceCpeBond(InterfaceHostTestCase): def _setup_configuration(self): # Setup a sample configuration where the personality is set to a # controller with a controller subfunction and all interfaces are # aggregated ethernet interfaces. self.host = self._create_test_host(constants.CONTROLLER) self._create_bond_test('oam', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_OAM) self._create_bond_test('mgmt', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT) self._create_bond_test('cluster-host', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_CLUSTER_HOST) self._create_bond_test('data', constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA) self._create_ethernet_test('sriov', constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV) self._create_ethernet_test('pthru', constants.INTERFACE_CLASS_PCI_PASSTHROUGH, constants.NETWORK_TYPE_PCI_PASSTHROUGH) def setUp(self): super(InterfaceCpeBond, self).setUp() self.expected_bmc_interface = 'mgmt' self.expected_platform_interfaces = ['eth0', 'eth1', 'oam', 'eth3', 'eth4', 'mgmt', 'eth6', 'eth7', 'cluster-host'] self.expected_data_interfaces = ['eth9', 'eth10', 'data'] self.expected_pci_interfaces = ['sriov', 'pthru'] self.expected_slave_interfaces = ['eth0', 'eth1', 'eth3', 'eth4', 'eth6', 'eth7', 'eth9', 'eth10', 'eth12', 'eth13'] class InterfaceCpeVlanOverBond(InterfaceHostTestCase): def _setup_configuration(self): # Setup a sample configuration where the personality is set to a # controller with a controller subfunction and all interfaces are # vlan interfaces over aggregated ethernet interfaces. self.host = self._create_test_host(constants.CONTROLLER) bond = self._create_bond_test('pxeboot', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_PXEBOOT) self._create_vlan_test('oam', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_OAM, 1, bond) self._create_vlan_test('mgmt', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT, 2, bond) self._create_vlan_test('cluster-host', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_CLUSTER_HOST, 3, bond) bond2 = self._create_bond_test('bond4') self._create_vlan_test('data', constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA, 5, bond2) self._create_ethernet_test('sriov', constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV) self._create_ethernet_test('pthru', constants.INTERFACE_CLASS_PCI_PASSTHROUGH, constants.NETWORK_TYPE_PCI_PASSTHROUGH) def setUp(self): super(InterfaceCpeVlanOverBond, self).setUp() self.expected_platform_interfaces = ['eth0', 'eth1', 'pxeboot', 'oam', 'mgmt', 'cluster-host'] self.expected_data_interfaces = ['eth6', 'eth7', 'bond4', 'data'] self.expected_slave_interfaces = ['eth0', 'eth1', 'eth6', 'eth7'] self.expected_pci_interfaces = ['sriov', 'pthru'] class InterfaceCpeComputeEthernet(InterfaceHostTestCase): def _setup_configuration(self): # Setup a sample configuration where the personality is set to a # controller with a worker subfunction and all interfaces are # ethernet interfaces. self.host = self._create_test_host(constants.CONTROLLER, constants.WORKER) self._create_ethernet_test('data', constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA) self._create_ethernet_test('sriov', constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV) self._create_ethernet_test('pthru', constants.INTERFACE_CLASS_PCI_PASSTHROUGH, constants.NETWORK_TYPE_PCI_PASSTHROUGH) self._create_ethernet_test('oam', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_OAM) self._create_ethernet_test('mgmt', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT) self._create_ethernet_test('cluster-host', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_CLUSTER_HOST) port, iface = ( self._create_ethernet_test('slow', constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA, dpdksupport=False)) port, iface = ( self._create_ethernet_test('mlx5', constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA, driver=constants.DRIVER_MLX_CX4)) self._create_ethernet_test('none') def setUp(self): super(InterfaceCpeComputeEthernet, self).setUp() self.expected_bmc_interface = 'mgmt' self.expected_platform_interfaces = ['oam', 'mgmt', 'cluster-host'] self.expected_data_interfaces = ['slow', 'data', 'mlx5'] self.expected_pci_interfaces = ['sriov', 'pthru'] self.expected_slow_interfaces = ['slow'] self.expected_bridged_interfaces = ['slow'] self.expected_slave_interfaces = [] self.expected_mlx_interfaces = ['mlx5'] class InterfaceCpeComputeVlanOverEthernet(InterfaceHostTestCase): def _setup_configuration(self): # Setup a sample configuration where the personality is set to a # controller with a worker subfunction and all interfaces are # vlan interfaces over ethernet interfaces. self.host = self._create_test_host(constants.CONTROLLER, constants.WORKER) port, iface = self._create_ethernet_test( 'pxeboot', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_PXEBOOT) self._create_vlan_test('oam', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_OAM, 1, iface) self._create_vlan_test('mgmt', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT, 2, iface) self._create_vlan_test('cluster-host', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_CLUSTER_HOST, 3) self._create_vlan_test('data', constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA, 5) self._create_ethernet_test('sriov', constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV) self._create_ethernet_test('pthru', constants.INTERFACE_CLASS_PCI_PASSTHROUGH, constants.NETWORK_TYPE_PCI_PASSTHROUGH) def setUp(self): super(InterfaceCpeComputeVlanOverEthernet, self).setUp() self.expected_bmc_interface = 'pxeboot' self.expected_platform_interfaces = ['pxeboot', 'oam', 'mgmt', 'eth3', 'cluster-host'] self.expected_data_interfaces = ['eth5', 'data'] self.expected_pci_interfaces = ['sriov', 'pthru'] class InterfaceCpeComputeBond(InterfaceHostTestCase): def _setup_configuration(self): # Setup a sample configuration where the personality is set to a # controller with a worker subfunction and all interfaces are # aggregated ethernet interfaces. self.host = self._create_test_host(constants.CONTROLLER, constants.WORKER) self._create_bond_test('oam', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_OAM) self._create_bond_test('mgmt', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT) self._create_bond_test('cluster-host', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_CLUSTER_HOST) self._create_bond_test('data', constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA) self._create_ethernet_test('sriov', constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV) self._create_ethernet_test('pthru', constants.INTERFACE_CLASS_PCI_PASSTHROUGH, constants.NETWORK_TYPE_PCI_PASSTHROUGH) def setUp(self): super(InterfaceCpeComputeBond, self).setUp() self.expected_bmc_interface = 'mgmt' self.expected_platform_interfaces = ['eth0', 'eth1', 'oam', 'eth3', 'eth4', 'mgmt', 'eth6', 'eth7', 'cluster-host'] self.expected_data_interfaces = ['eth9', 'eth10', 'data'] self.expected_pci_interfaces = ['sriov', 'pthru'] self.expected_slave_interfaces = ['eth0', 'eth1', 'eth3', 'eth4', 'eth6', 'eth7', 'eth9', 'eth10', 'eth12', 'eth13'] class InterfaceCpeComputeVlanOverBond(InterfaceHostTestCase): def _setup_configuration(self): # Setup a sample configuration where the personality is set to a # controller with a worker subfunction and all interfaces are # vlan interfaces over aggregated ethernet interfaces. self.host = self._create_test_host(constants.CONTROLLER, constants.WORKER) bond = self._create_bond_test('pxeboot', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_PXEBOOT) self._create_vlan_test('oam', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_OAM, 1, bond) self._create_vlan_test('mgmt', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT, 2, bond) self._create_vlan_test('cluster-host', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_CLUSTER_HOST, 3, bond) bond2 = self._create_bond_test('bond2') self._create_vlan_test('data', constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA, 5, bond2) self._create_ethernet_test('sriov', constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV) self._create_ethernet_test('pthru', constants.INTERFACE_CLASS_PCI_PASSTHROUGH, constants.NETWORK_TYPE_PCI_PASSTHROUGH) def setUp(self): super(InterfaceCpeComputeVlanOverBond, self).setUp() self.expected_platform_interfaces = ['eth0', 'eth1', 'pxeboot', 'oam', 'mgmt', 'cluster-host'] self.expected_data_interfaces = ['eth6', 'eth7', 'bond2', 'data'] self.expected_slave_interfaces = ['eth0', 'eth1', 'eth6', 'eth7'] self.expected_pci_interfaces = ['sriov', 'pthru'] # Mnemonics for building expected interface configs NET = 'net' # Expected network type, constants.NETWORK_TYPE_ or None FAMILY = 'family' # Expected family, INET or INET6 INET = 'inet' # Value 'inet' for expected FAMILY INET6 = 'inet6' # Value 'inet6' for expected FAMILY METHOD = 'method' # Expected method, STATIC or MANUAL STATIC = 'static' # Value 'static' for expected METHOD MANUAL = 'manual' # Value 'manual' for expected METHOD DHCP = 'dhcp' # Value 'dhcp' for expected METHOD OPTIONS = 'options' # Expected options, dictionary GATEWAY = 'gateway' # Option 'gateway', True if gateway address must be present ALLOW = 'allow' # Option 'allow-' for bond slaves, True if must be present UP = 'up' # Option 'up' operation, should be a list of command mnemonics PRE_UP = 'pre-up' # Option 'pre-up' operation, should be a list of command mnemonics POST_UP = 'post-up' # Option 'post-up' operation, should be a list of command mnemonics DOWN = 'down' # Option 'down' operation, should be a list of command mnemonics PRE_DOWN = 'pre-down' # Option 'pre-down' operation, should be a list of command mnemonics POST_DOWN = 'post-down' # Option 'post-down' operation, should be a list of command mnemonics IPV6_CFG = 'ipv6-cfg' # Operation command to set IPv6 autoconf, accept_ra and accept_redirects SET_MTU = 'set-mtu' # Operation command to set MTU SET_TC = 'set-tc' # Operation command to configure traffic classifier VLAN_MOD = 'vlan-mod' # Operation command to add vlan kernel module VLAN_ADD = 'vlan-add' # Operation command to create vlan VLAN_DEL = 'vlan-del' # Operation command to remove vlan PROMISC_ON = 'prmsc-on' # Operation command to enable promiscuous mode UNDEPR = 'undepr' # Operation command to undeprecate IPv6 address SRIOV = 'sriov' # Operation command to setup sriov PTHROUGH = 'pthrough' # Operation command to setup pass-through SLEEP = 'sleep' # Operation command to sleep for 10 seconds BOND_SETUP = 'bond-stp' # Operation command to setup bond DIS_DAD = 'disable-dad' # Operation command to disable DAD MODES = 'modes' # List of modes where this configuration is expected, all if unspecified SS_IPV4 = 'ss-ipv4' # Configuration is expected for Single Stack IPv4 mode SS_IPV6 = 'ss-ipv6' # Configuration is expected for Single Stack IPv6 mode DS_IPV4 = 'ds-ipv4' # Configuration is expected for Dual Stack / Primary IPv4 mode DS_IPV6 = 'ds-ipv6' # Configuration is expected for Dual Stack / Primary IPv6 mode OPERATIONS = [UP, PRE_UP, POST_UP, DOWN, PRE_DOWN, POST_DOWN] class InterfaceConfigTestMixin(InterfaceTestCaseMixin): def setUp(self): super(InterfaceConfigTestMixin, self).setUp() self._setup_context() def _setup_configuration(self): self.interface_index = {} self.new_address_index = {} def _update_context(self): # skip automatic context update pass def _do_update_context(self): super(InterfaceConfigTestMixin, self)._update_context() debuglevel = int(os.environ.get('TOX_DEBUG_LEVEL', '0')) def _include_interface(self, iface, info): iface_dict = { 'interface': iface, 'info': info, 'networks': { None: { 'network': None, 'addresses': { constants.IPV4_FAMILY: [], constants.IPV6_FAMILY: [], } } }, 'gateways': {} } self.interface_index[iface.ifname] = iface_dict return iface_dict def _include_network(self, iface, network): self.interface_index[iface.ifname]['networks'][network.id] = { 'network': network, 'addresses': { constants.IPV4_FAMILY: [], constants.IPV6_FAMILY: [], } } def _include_address(self, iface, network, address): network_id = network.id if network else None (self.interface_index[iface.ifname]['networks'][network_id]['addresses'] [address.family]).append(address) def _include_gateway(self, iface, address, gateway): self.interface_index[iface.ifname]['gateways'][address.id] = gateway def _get_new_address(self, addrpool, family=None): id = addrpool.id if addrpool else -int(family) entry = self.new_address_index.get(id, None) if not entry: if addrpool: ipnetwork = netaddr.IPNetwork(addrpool.network + '/' + str(addrpool.prefix)) else: if family == constants.IPV6_FAMILY: ipnetwork = netaddr.IPNetwork('fda0::/64') else: ipnetwork = netaddr.IPNetwork('192.168.100.0/24') entry = {'ipnetwork': ipnetwork, 'offset': 10} self.new_address_index[id] = entry offset = entry['offset'] entry['offset'] += 1 return str(entry['ipnetwork'][offset]), entry['ipnetwork'].prefixlen def _get_new_pool_address(self, addrpool): return self._get_new_address(addrpool) def _get_new_detached_address(self, family): return self._get_new_address(None, family) def _setup_detached_address(self, iface, family): addr, prefixlen = self._get_new_detached_address(family) address = self._create_test_address( name=f"{iface.ifname}-detached-ipv{family}", family=family, prefix=prefixlen, address=addr, interface_id=iface.id) if (family == constants.IPV4_FAMILY and iface.ipv4_mode == constants.IPV4_STATIC or family == constants.IPV6_FAMILY and iface.ipv6_mode == constants.IPV6_STATIC): self._include_address(iface, None, address) def _setup_detached_addresses(self, iface): iface_info = self.interface_index[iface.ifname]['info'] for _ in range(iface_info['ipv4_addresses']): self._setup_detached_address(iface, constants.IPV4_FAMILY) for _ in range(iface_info['ipv6_addresses']): self._setup_detached_address(iface, constants.IPV6_FAMILY) def _assign_address_to_interface(self, iface, address): dbapi = db_api.get_instance() dbapi.address_update(address.uuid, {'interface_id': iface.id}) address.interface_id = iface.id address.ifname = iface.ifname def _get_controller_pool_address(self, iface, addrpool): self.assertIsNotNone(addrpool.controller0_address_id) address = self._find_address_by_id(addrpool.controller0_address_id) self._assign_address_to_interface(iface, address) return address def _create_non_controller_pool_address(self, iface, network, addrpool): addr, prefixlen = self._get_new_pool_address(addrpool) return self._create_test_address( name=utils.format_address_name(self.host.hostname, network.type), family=addrpool.family, prefix=prefixlen, address=addr, interface_id=iface.id, address_pool_id=addrpool.id) def _setup_gateway(self, iface, network, addrpool, address): if (network and network.type == constants.NETWORK_TYPE_MGMT and self.host.personality in [constants.WORKER, constants.STORAGE]): gateway_address = addrpool.floating_address else: gateway_address = addrpool.gateway_address self._include_gateway(iface, address, gateway_address) def _setup_pool_address(self, iface, network, addrpool): if self.host.personality == constants.CONTROLLER: address = self._get_controller_pool_address(iface, addrpool) else: address = self._create_non_controller_pool_address(iface, network, addrpool) self._include_address(iface, network, address) self._setup_gateway(iface, network, addrpool, address) def _setup_network_and_addresses(self, iface, networktype): network = self._find_network_by_type(networktype) self._include_network(iface, network) if self.host.personality != constants.CONTROLLER: if networktype not in [constants.NETWORK_TYPE_MGMT, constants.NETWORK_TYPE_CLUSTER_HOST, constants.NETWORK_TYPE_STORAGE, constants.NETWORK_TYPE_ADMIN]: return addrpools = self._find_network_address_pools(network.id) for addrpool in addrpools: self._setup_pool_address(iface, network, addrpool) def _setup_networks_and_addresses(self, iface): for networktype in iface.networktypelist: self._setup_network_and_addresses(iface, networktype) def _setup_addresses(self, iface): if iface.ifclass == constants.INTERFACE_CLASS_DATA: self._setup_detached_addresses(iface) elif iface.ifclass == constants.INTERFACE_CLASS_PLATFORM: if iface.networktypelist: self._setup_networks_and_addresses(iface) else: self._setup_detached_addresses(iface) def _setup_interface(self, iface, interface_info): self._include_interface(iface, interface_info) self._setup_addresses(iface) def _build_interface_info(self, **kwargs): return {'kernel_name': kwargs.get('kernel_name', None), 'upper_device': kwargs.get('upper_device', None), 'bond_slaves': kwargs.get('bond_slaves', None), 'bond_primary': kwargs.get('bond_primary', None), 'dpdksupport': kwargs.get('dpdksupport', True), 'driver': kwargs.get('driver', None), 'ipv4_addresses': kwargs.get('ipv4_addresses', 0), 'ipv6_addresses': kwargs.get('ipv6_addresses', 0)} def _setup_bond_slave(self, port, iface, master_info): interface_info = self._build_interface_info( kernel_name=port.name, upper_device=master_info['kernel_name'], is_slave=True) self._setup_interface(iface, interface_info) def _get_address_netmask(self, address): network = netaddr.IPNetwork(address.address + '/' + str(address.prefix)) if network.version == constants.IPV6_FAMILY: return str(network.prefixlen) else: return str(network.netmask) def _get_stx_description(self, iface, network): networktext = network.type if network else 'None' return f"ifname:{iface.ifname},net:{networktext}" def _get_traffic_classifier_cmd(self, iface, kernel_name): if constants.NETWORK_TYPE_MGMT in iface.networktypelist: cmd = '%s %s %s %s > /dev/null' % (constants.TRAFFIC_CONTROL_SCRIPT, kernel_name, constants.NETWORK_TYPE_MGMT, constants.LINK_SPEED_10G) return [cmd] return [] def _get_cmd_ipv6_autoconf_off(self, os_ifname): return ['echo 0 > /proc/sys/net/ipv6/conf/{}/autoconf'.format(os_ifname), 'echo 0 > /proc/sys/net/ipv6/conf/{}/accept_ra'.format(os_ifname), 'echo 0 > /proc/sys/net/ipv6/conf/{}/accept_redirects'.format(os_ifname)] def _get_cmd_postup_mtu(self, os_ifname, mtu): return ['/usr/sbin/ip link set dev {} mtu {}'.format(os_ifname, mtu)] def _get_cmd_vlan_kernel_module(self): return ['/sbin/modprobe -q 8021q'] def _get_cmd_vlan_creation(self, raw_device, kernel_name, vlan_id): return ['ip link add link {} name {} type vlan id {}'.format( raw_device, kernel_name, vlan_id)] def _get_cmd_vlan_removal(self, kernel_name): return ['ip link del {}'.format(kernel_name)] def _get_promisc_cmd(self, kernel_name): return ['/usr/sbin/ip link set dev {} promisc on'.format(kernel_name)] def _get_undeprecate_cmd(self, kernel_name, address): return ['ip -6 addr replace {}/{} dev {} preferred_lft forever'.format( address.address, address.prefix, kernel_name)] def _get_sriov_numvfs_path(self, port): return '/sys/class/net/{}/device/sriov_numvfs'.format(port) def _get_sriov_numvfs_cmd(self, port, numvfs): sriovfs_path = self._get_sriov_numvfs_path(port) return ['echo 0 > {}'.format(sriovfs_path), 'echo {} > {}'.format(numvfs, sriovfs_path)] def _get_pci_passthrough_numvfs_cmd(self, port): sriovfs_path = self._get_sriov_numvfs_path(port) return ['if [ -f {0} ]; then echo 0 > {0}; fi'.format(sriovfs_path)] def _get_sleep_cmd(self): return ['sleep 10'] def _get_bonding_setup_cmd(self, kernel_name): return ['/sbin/modprobe bonding', 'grep %s /sys/class/net/bonding_masters || ' 'echo +%s > /sys/class/net/bonding_masters' % (kernel_name, kernel_name)] def _get_disable_dad_cmd(self, kernel_name): return ["sysctl -wq net.ipv6.conf.%s.accept_dad=0" % kernel_name] def _get_operations(self, iface_dict, commands, address): iface = iface_dict['interface'] kernel_name = iface_dict['info']['kernel_name'] operation_list = [] for command in commands: if command == IPV6_CFG: operation_list.extend(self._get_cmd_ipv6_autoconf_off(kernel_name)) elif command == SET_MTU: operation_list.extend(self._get_cmd_postup_mtu(kernel_name, iface.imtu)) elif command == SET_TC: operation_list.extend(self._get_traffic_classifier_cmd(iface, kernel_name)) elif command == VLAN_MOD: operation_list.extend(self._get_cmd_vlan_kernel_module()) elif command == VLAN_ADD: operation_list.extend(self._get_cmd_vlan_creation( iface_dict['info']['upper_device'], kernel_name, iface.vlan_id)) elif command == VLAN_DEL: operation_list.extend(self._get_cmd_vlan_removal(kernel_name)) elif command == PROMISC_ON: operation_list.extend(self._get_promisc_cmd(kernel_name)) elif command == UNDEPR: operation_list.extend(self._get_undeprecate_cmd(kernel_name, address)) elif command == SRIOV: operation_list.extend(self._get_sriov_numvfs_cmd(kernel_name, iface.sriov_numvfs)) elif command == PTHROUGH: operation_list.extend(self._get_pci_passthrough_numvfs_cmd(kernel_name)) elif command == SLEEP: operation_list.extend(self._get_sleep_cmd()) elif command == BOND_SETUP: operation_list.extend(self._get_bonding_setup_cmd(kernel_name)) elif command == DIS_DAD: operation_list.extend(self._get_disable_dad_cmd(kernel_name)) return '; '.join(operation_list) def _get_ifcfg_options(self, iface_dict, network, address, exp_cfg): iface = iface_dict['interface'] exp_options = exp_cfg[OPTIONS] options = {'mtu': str(iface_dict['interface'].imtu), 'stx-description': self._get_stx_description(iface, network)} if exp_options.pop('vlan-raw-device', False): self.assertEqual(iface.iftype, constants.INTERFACE_TYPE_VLAN, f"Interface {iface.ifname} is not VLAN") options['vlan-raw-device'] = iface_dict['info']['upper_device'] if exp_options.pop('hwaddress', False): options['hwaddress'] = iface.imac.rstrip() if exp_options.pop('bond-primary', False): options['bond-primary'] = iface_dict['info']['bond_primary'] if exp_options.pop('bond-slaves', False): options['bond-slaves'] = iface_dict['info']['bond_slaves'] if exp_options.pop('bond-master', False): options['bond-master'] = iface_dict['info']['upper_device'] if exp_options.pop(ALLOW, False): key = 'allow-{}'.format(iface_dict['info']['upper_device']) options[key] = iface_dict['info']['kernel_name'] for oper in OPERATIONS: oper_list = exp_options.pop(oper, None) if oper_list: options[oper] = self._get_operations(iface_dict, oper_list, address) options.update(exp_options) return options def _get_expected_interface_config(self, iface_dict, network, address, exp_cfg, base): iface = iface_dict['interface'] has_gateway = exp_cfg[OPTIONS].pop(GATEWAY, False) config = { 'ensure': 'present', 'onboot': 'true', 'hotplug': 'false', 'family': exp_cfg[FAMILY], 'method': exp_cfg[METHOD], 'options': self._get_ifcfg_options(iface_dict, network, address, exp_cfg)} if exp_cfg[METHOD] == STATIC: self.assertIsNotNone(address, f"Address expected for interface {iface.ifname} / " f"network {network.type if network else None}, but not present") config['ipaddress'] = address.address config['netmask'] = self._get_address_netmask(address) if has_gateway: gateway = iface_dict['gateways'].get(address.id, None) self.assertIsNotNone(gateway, f"Gateway expected for interface {iface.ifname} / " f"network {network.type if network else None} / " f"address {address.address} but not present") config['options']['gateway'] = gateway kernelname = iface_dict['info']['kernel_name'] if base: ifname = kernelname else: ifname = f"{kernelname}:{network.id if network else 0}-{address.id if address else 0}" return {ifname: config} def _get_address(self, iface_dict, network, family, index): network_id = network.id if network else None self.assertIn(network_id, iface_dict['networks'], f"Network '{network.type if network else None}' is not associated" f"with interface '{iface_dict['interface'].ifname}'") addr_list = iface_dict['networks'][network_id]['addresses'][family] self.assertGreater(len(addr_list), index, f"There are only {len(addr_list)} IPv{family} addresses associated with interface " f"{iface_dict['interface'].ifname} for network {network.type if network else None}," f" index {index + 1} is out of bounds") return addr_list[index] def _is_config_included(self, exp_cfg): modes = exp_cfg.pop(MODES, None) if not modes: return True return self.system_mode in modes def _get_expected_interface_configs(self, ifname, expected_iface_configs): self.assertIn(ifname, self.interface_index, f"Interface {ifname} was not created") iface_dict = self.interface_index[ifname] address_index = defaultdict(lambda: defaultdict(int)) base = True interface_configs = {} for exp_cfg in expected_iface_configs: if not self._is_config_included(exp_cfg): continue network = self._find_network_by_type(exp_cfg[NET]) network_id = network.id if network else None if network_id not in iface_dict['networks']: if (network.type == constants.NETWORK_TYPE_PXEBOOT and constants.NETWORK_TYPE_MGMT in iface_dict['interface'].networktypelist): self._setup_network_and_addresses(iface_dict['interface'], network.type) address = None if exp_cfg[METHOD] == STATIC: if exp_cfg[FAMILY] == INET6: family = constants.IPV6_FAMILY else: family = constants.IPV4_FAMILY address = self._get_address(iface_dict, network, family, address_index[network_id][family]) address_index[network_id][family] += 1 config = self._get_expected_interface_config(iface_dict, network, address, exp_cfg, base) interface_configs.update(config) base = False return interface_configs def _add_loopback_config(self, interface_configs): interface_configs['lo'] = {'ensure': 'present', 'family': 'inet', 'hotplug': 'false', 'method': 'loopback', 'onboot': 'true', 'options': {}} def _get_expected_config(self, expected_configs): interface_configs = {} for ifname, expected_iface_configs in expected_configs.items(): configs = self._get_expected_interface_configs(ifname, expected_iface_configs) interface_configs.update(configs) self._add_loopback_config(interface_configs) return interface_configs def _get_generated_config(self): hiera_data = self.operator.interface.get_host_config(self.host) self.assertIn('platform::network::interfaces::network_config', hiera_data) return hiera_data['platform::network::interfaces::network_config'] def _remove_non_serializable_elements(self, object_vars): object_vars.pop('_changed_fields', None) object_vars.pop('_created_at', None) object_vars.pop('_updated_at', None) return object_vars # Prints interface index contents for debug purposes def _print_interface_index(self): printable_interface_index = {} for interface_dict in self.interface_index.values(): interface = interface_dict['interface'] printable_network_dict = {} for network_dict in interface_dict['networks'].values(): network = network_dict['network'] printable_address_index = defaultdict(list) for family, addresses in network_dict['addresses'].items(): for address in addresses: printable_address_index[family].append( self._remove_non_serializable_elements(vars(address))) printable_network_dict[network.id if network else 0] = { 'network': (self._remove_non_serializable_elements(vars(network)) if network else None), 'addresses': printable_address_index} printable_interface_index[interface.ifname] = { 'interface': self._remove_non_serializable_elements(vars(interface)), 'info': interface_dict['info'], 'networks': printable_network_dict} print(json.dumps(printable_interface_index, sort_keys=True, indent=4)) def _create_host(self, personality=constants.CONTROLLER, subfunction=None): self.host = self._create_test_host(personality, subfunction) def _add_ethernet(self, ifname=None, ifclass=None, networktype=None, **kwargs): port, iface = self._create_ethernet_test(ifname, ifclass, networktype, **kwargs) driver = kwargs.get('driver', 'ixgbe') interface_info = self._build_interface_info( kernel_name=port.name, dpdksupport=kwargs.get('dpdksupport', True), driver=driver, ipv4_addresses=kwargs.get('ipv4_addresses', 0), ipv6_addresses=kwargs.get('ipv6_addresses', 0)) self._setup_interface(iface, interface_info) return iface def _add_bond(self, ifname=None, ifclass=None, networktype=None, **kwargs): port1, slave1 = self._create_ethernet_test() port2, slave2 = self._create_ethernet_test() iface = self._create_bond_test(ifname, ifclass, networktype, iface1=slave1, iface2=slave2, **kwargs) interface_info = self._build_interface_info( kernel_name=iface.ifname, bond_slaves='{} {} '.format(port1.name, port2.name), bond_primary=port1.name, ipv4_addresses=kwargs.get('ipv4_addresses', 0), ipv6_addresses=kwargs.get('ipv6_addresses', 0)) self._setup_interface(iface, interface_info) self._setup_bond_slave(port1, slave1, interface_info) self._setup_bond_slave(port2, slave2, interface_info) return iface def _add_vlan(self, lower_iface, vlan_id, ifname=None, ifclass=None, networktype=None, **kwargs): iface = self._create_vlan_test(ifname, ifclass, networktype, vlan_id, lower_iface, **kwargs) lower_iface_dict = self.interface_index[lower_iface.ifname] lower_iface_info = lower_iface_dict['info'] interface_info = self._build_interface_info( kernel_name=interface.get_vlan_os_ifname(iface), upper_device=lower_iface_info['kernel_name'], ipv4_addresses=kwargs.get('ipv4_addresses', 0), ipv6_addresses=kwargs.get('ipv6_addresses', 0)) self._setup_interface(iface, interface_info) return iface def _validate_config(self, expected): self._do_update_context() expected_config = self._get_expected_config(expected) if self.debuglevel >= 2: self._print_interface_index() generated_config = self._get_generated_config() self.assertEqual(expected_config, generated_config) if self.debuglevel >= 1: print(json.dumps(generated_config, sort_keys=True, indent=4)) def test_controller_ethernet_oam(self): self._create_host(constants.CONTROLLER) self._add_ethernet('oam0', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_OAM) expected = { 'oam0': [ {MODES: [DS_IPV4, DS_IPV6], NET: None, FAMILY: INET, METHOD: MANUAL, OPTIONS: {POST_UP: [SET_TC, IPV6_CFG]}}, {MODES: [SS_IPV4, DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_OAM, FAMILY: INET, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG]}}, {MODES: [SS_IPV6], NET: constants.NETWORK_TYPE_OAM, FAMILY: INET6, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [SET_TC, IPV6_CFG]}}, {MODES: [DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_OAM, FAMILY: INET6, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG]}}], } self._validate_config(expected) def test_controller_ethernet_separate_nets_pxeboot_unassigned(self): self._create_host(constants.CONTROLLER) self._add_ethernet('mgmt0', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT) self._add_ethernet('clhost0', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_CLUSTER_HOST) self._add_ethernet('none') expected = { 'mgmt0': [ {NET: None, FAMILY: INET, METHOD: MANUAL, OPTIONS: {POST_UP: [SET_TC, IPV6_CFG]}}, {NET: constants.NETWORK_TYPE_PXEBOOT, FAMILY: INET, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG]}}, {MODES: [SS_IPV4, DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_MGMT, FAMILY: INET, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG]}}, {MODES: [SS_IPV6, DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_MGMT, FAMILY: INET6, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG, UNDEPR]}}], 'clhost0': [ {MODES: [DS_IPV4, DS_IPV6], NET: None, FAMILY: INET, METHOD: MANUAL, OPTIONS: {POST_UP: [SET_TC, IPV6_CFG]}}, {MODES: [SS_IPV4], NET: constants.NETWORK_TYPE_CLUSTER_HOST, FAMILY: INET, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG]}}, {MODES: [DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_CLUSTER_HOST, FAMILY: INET, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG]}}, {MODES: [SS_IPV6], NET: constants.NETWORK_TYPE_CLUSTER_HOST, FAMILY: INET6, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [SET_TC, IPV6_CFG]}}, {MODES: [DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_CLUSTER_HOST, FAMILY: INET6, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG, UNDEPR]}}], } self._validate_config(expected) def test_controller_ethernet_joined_nets_pxeboot_unassigned(self): self._create_host(constants.CONTROLLER) self._add_ethernet('mgmt0', constants.INTERFACE_CLASS_PLATFORM, [constants.NETWORK_TYPE_MGMT, constants.NETWORK_TYPE_CLUSTER_HOST]) self._add_ethernet('none') expected = { 'mgmt0': [ {NET: None, FAMILY: INET, METHOD: MANUAL, OPTIONS: {POST_UP: [SET_TC, IPV6_CFG]}}, {NET: constants.NETWORK_TYPE_PXEBOOT, FAMILY: INET, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG]}}, {MODES: [SS_IPV4, DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_MGMT, FAMILY: INET, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG]}}, {MODES: [SS_IPV6, DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_MGMT, FAMILY: INET6, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG, UNDEPR]}}, {MODES: [SS_IPV4, DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_CLUSTER_HOST, FAMILY: INET, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG]}}, {MODES: [SS_IPV6, DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_CLUSTER_HOST, FAMILY: INET6, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG]}}], } self._validate_config(expected) def test_controller_ethernet_joined_nets_pxeboot_assigned(self): self._create_host(constants.CONTROLLER) self._add_ethernet('mgmt0', constants.INTERFACE_CLASS_PLATFORM, [constants.NETWORK_TYPE_MGMT, constants.NETWORK_TYPE_CLUSTER_HOST, constants.NETWORK_TYPE_PXEBOOT]) self._add_ethernet('none') expected = { 'mgmt0': [ {NET: None, FAMILY: INET, METHOD: MANUAL, OPTIONS: {POST_UP: [SET_TC, IPV6_CFG]}}, {NET: constants.NETWORK_TYPE_PXEBOOT, FAMILY: INET, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG]}}, {MODES: [SS_IPV4, DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_MGMT, FAMILY: INET, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG]}}, {MODES: [SS_IPV6, DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_MGMT, FAMILY: INET6, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG, UNDEPR]}}, {MODES: [SS_IPV4, DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_CLUSTER_HOST, FAMILY: INET, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG]}}, {MODES: [SS_IPV6, DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_CLUSTER_HOST, FAMILY: INET6, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG]}}], } self._validate_config(expected) def test_controller_ethernet_separate_nets_pxeboot_assigned(self): self._create_host(constants.CONTROLLER) self._add_ethernet('pxe0', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_PXEBOOT) self._add_ethernet('mgmt0', constants.INTERFACE_CLASS_PLATFORM, [constants.NETWORK_TYPE_MGMT, constants.NETWORK_TYPE_CLUSTER_HOST]) self._add_ethernet('none') expected = { 'pxe0': [ {NET: constants.NETWORK_TYPE_PXEBOOT, FAMILY: INET, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG]}}], 'mgmt0': [ {NET: None, FAMILY: INET, METHOD: MANUAL, OPTIONS: {POST_UP: [SET_TC, IPV6_CFG]}}, {MODES: [SS_IPV4, DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_MGMT, FAMILY: INET, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG]}}, {MODES: [SS_IPV6, DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_MGMT, FAMILY: INET6, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG, UNDEPR]}}, {MODES: [SS_IPV4, DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_CLUSTER_HOST, FAMILY: INET, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG]}}, {MODES: [SS_IPV6, DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_CLUSTER_HOST, FAMILY: INET6, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG]}}], } self._validate_config(expected) def test_controller_vlan_over_bond(self): self._create_host(constants.CONTROLLER) pxe0 = self._add_bond('pxe0', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_PXEBOOT) self._add_vlan(pxe0, 100, 'mgmt0', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT) self._add_vlan(pxe0, 200, 'clhost0', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_CLUSTER_HOST) expected = { 'pxe0': [ {NET: constants.NETWORK_TYPE_PXEBOOT, FAMILY: INET, METHOD: STATIC, OPTIONS: {GATEWAY: True, 'bond-lacp-rate': 'fast', 'bond-miimon': '100', 'bond-mode': '802.3ad', 'bond-slaves': True, 'bond-xmit-hash-policy': 'layer2', 'hwaddress': True, POST_UP: [SET_TC, IPV6_CFG], UP: [SLEEP]}}], 'eth0': [ {NET: None, FAMILY: INET, METHOD: MANUAL, OPTIONS: {ALLOW: True, 'bond-master': True, PRE_UP: [PROMISC_ON, IPV6_CFG]}}], 'eth1': [ {NET: None, FAMILY: INET, METHOD: MANUAL, OPTIONS: {ALLOW: True, 'bond-master': True, PRE_UP: [PROMISC_ON, IPV6_CFG]}}], 'mgmt0': [ {MODES: [DS_IPV4, DS_IPV6], NET: None, FAMILY: INET, METHOD: MANUAL, OPTIONS: {'vlan-raw-device': True, PRE_UP: [VLAN_MOD], POST_UP: [SET_TC, SET_MTU, IPV6_CFG]}}, {MODES: [SS_IPV4], NET: constants.NETWORK_TYPE_MGMT, FAMILY: INET, METHOD: STATIC, OPTIONS: {GATEWAY: True, 'vlan-raw-device': True, PRE_UP: [VLAN_MOD], POST_UP: [SET_MTU, IPV6_CFG, SET_TC]}}, {MODES: [DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_MGMT, FAMILY: INET, METHOD: STATIC, OPTIONS: {GATEWAY: True, 'vlan-raw-device': True, PRE_UP: [VLAN_MOD], POST_UP: [SET_MTU, IPV6_CFG]}}, {MODES: [SS_IPV6], NET: constants.NETWORK_TYPE_MGMT, FAMILY: INET6, METHOD: STATIC, OPTIONS: {GATEWAY: True, 'vlan-raw-device': True, PRE_UP: [VLAN_MOD], POST_UP: [SET_MTU, IPV6_CFG, SET_TC]}}, {MODES: [DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_MGMT, FAMILY: INET6, METHOD: STATIC, OPTIONS: {GATEWAY: True, 'vlan-raw-device': True, PRE_UP: [VLAN_MOD], POST_UP: [SET_MTU, IPV6_CFG, UNDEPR]}}], 'clhost0': [ {MODES: [DS_IPV4, DS_IPV6], NET: None, FAMILY: INET, METHOD: MANUAL, OPTIONS: {'vlan-raw-device': True, PRE_UP: [VLAN_MOD], POST_UP: [SET_TC, SET_MTU, IPV6_CFG]}}, {MODES: [SS_IPV4], NET: constants.NETWORK_TYPE_CLUSTER_HOST, FAMILY: INET, METHOD: STATIC, OPTIONS: {GATEWAY: True, 'vlan-raw-device': True, PRE_UP: [VLAN_MOD], POST_UP: [SET_MTU, IPV6_CFG, SET_TC]}}, {MODES: [DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_CLUSTER_HOST, FAMILY: INET, METHOD: STATIC, OPTIONS: {GATEWAY: True, 'vlan-raw-device': True, PRE_UP: [VLAN_MOD], POST_UP: [SET_MTU, IPV6_CFG]}}, {MODES: [SS_IPV6], NET: constants.NETWORK_TYPE_CLUSTER_HOST, FAMILY: INET6, METHOD: STATIC, OPTIONS: {GATEWAY: True, 'vlan-raw-device': True, PRE_UP: [VLAN_MOD], POST_UP: [SET_MTU, IPV6_CFG, SET_TC]}}, {MODES: [DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_CLUSTER_HOST, FAMILY: INET6, METHOD: STATIC, OPTIONS: {GATEWAY: True, 'vlan-raw-device': True, PRE_UP: [VLAN_MOD], POST_UP: [SET_MTU, IPV6_CFG, UNDEPR]}}], } self._validate_config(expected) def test_controller_duplex_direct_ethernet(self): self._create_host(constants.CONTROLLER) system_dict = self.system.as_dict() system_dict['system_mode'] = constants.SYSTEM_MODE_DUPLEX_DIRECT self.dbapi.isystem_update(self.system.uuid, system_dict) self._add_ethernet('mgmt0', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT) self._add_ethernet('clhost0', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_CLUSTER_HOST) expected = { 'mgmt0': [ {NET: None, FAMILY: INET, METHOD: MANUAL, OPTIONS: {PRE_UP: [DIS_DAD], POST_UP: [SET_TC, IPV6_CFG]}}, {NET: constants.NETWORK_TYPE_PXEBOOT, FAMILY: INET, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG]}}, {MODES: [SS_IPV4, DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_MGMT, FAMILY: INET, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG]}}, {MODES: [SS_IPV6, DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_MGMT, FAMILY: INET6, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG, UNDEPR]}}], 'clhost0': [ {MODES: [DS_IPV4, DS_IPV6], NET: None, FAMILY: INET, METHOD: MANUAL, OPTIONS: {PRE_UP: [DIS_DAD], POST_UP: [SET_TC, IPV6_CFG]}}, {MODES: [SS_IPV4], NET: constants.NETWORK_TYPE_CLUSTER_HOST, FAMILY: INET, METHOD: STATIC, OPTIONS: {GATEWAY: True, PRE_UP: [DIS_DAD], POST_UP: [IPV6_CFG]}}, {MODES: [DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_CLUSTER_HOST, FAMILY: INET, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG]}}, {MODES: [SS_IPV6], NET: constants.NETWORK_TYPE_CLUSTER_HOST, FAMILY: INET6, METHOD: STATIC, OPTIONS: {GATEWAY: True, PRE_UP: [DIS_DAD], POST_UP: [SET_TC, IPV6_CFG]}}, {MODES: [DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_CLUSTER_HOST, FAMILY: INET6, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG, UNDEPR]}}], } self._validate_config(expected) def test_controller_duplex_direct_vlan_over_bond(self): self._create_host(constants.CONTROLLER) system_dict = self.system.as_dict() system_dict['system_mode'] = constants.SYSTEM_MODE_DUPLEX_DIRECT self.dbapi.isystem_update(self.system.uuid, system_dict) pxe0 = self._add_ethernet('pxe0', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_PXEBOOT) self._add_bond('mgmt0', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT) self._add_vlan(pxe0, 200, 'clhost0', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_CLUSTER_HOST) expected = { 'pxe0': [ {NET: constants.NETWORK_TYPE_PXEBOOT, FAMILY: INET, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG]}}], 'mgmt0': [ {MODES: [DS_IPV4, DS_IPV6], NET: None, FAMILY: INET, METHOD: MANUAL, OPTIONS: {'bond-lacp-rate': 'fast', 'bond-miimon': '100', 'bond-mode': '802.3ad', 'bond-slaves': True, 'bond-xmit-hash-policy': 'layer2', 'hwaddress': True, PRE_UP: [BOND_SETUP, DIS_DAD], POST_UP: [SET_TC, IPV6_CFG], UP: [SLEEP]}}, {MODES: [SS_IPV4], NET: constants.NETWORK_TYPE_MGMT, FAMILY: INET, METHOD: STATIC, OPTIONS: {GATEWAY: True, 'bond-lacp-rate': 'fast', 'bond-miimon': '100', 'bond-mode': '802.3ad', 'bond-slaves': True, 'bond-xmit-hash-policy': 'layer2', 'hwaddress': True, PRE_UP: [BOND_SETUP, DIS_DAD], POST_UP: [IPV6_CFG, SET_TC], UP: [SLEEP]}}, {MODES: [DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_MGMT, FAMILY: INET, METHOD: STATIC, OPTIONS: {GATEWAY: True, 'bond-lacp-rate': 'fast', 'bond-miimon': '100', 'bond-mode': '802.3ad', 'bond-slaves': True, 'bond-xmit-hash-policy': 'layer2', 'hwaddress': True, POST_UP: [IPV6_CFG], UP: [SLEEP]}}, {MODES: [SS_IPV6], NET: constants.NETWORK_TYPE_MGMT, FAMILY: INET6, METHOD: STATIC, OPTIONS: {GATEWAY: True, 'bond-lacp-rate': 'fast', 'bond-miimon': '100', 'bond-mode': '802.3ad', 'bond-slaves': True, 'bond-xmit-hash-policy': 'layer2', 'hwaddress': True, PRE_UP: [BOND_SETUP, DIS_DAD], POST_UP: [IPV6_CFG, SET_TC], UP: [SLEEP]}}, {MODES: [DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_MGMT, FAMILY: INET6, METHOD: STATIC, OPTIONS: {GATEWAY: True, 'bond-lacp-rate': 'fast', 'bond-miimon': '100', 'bond-mode': '802.3ad', 'bond-slaves': True, 'bond-xmit-hash-policy': 'layer2', 'hwaddress': True, POST_UP: [IPV6_CFG, UNDEPR], UP: [SLEEP]}}], 'eth1': [ {NET: None, FAMILY: INET, METHOD: MANUAL, OPTIONS: {ALLOW: True, 'bond-master': True, PRE_UP: [PROMISC_ON, IPV6_CFG]}}], 'eth2': [ {NET: None, FAMILY: INET, METHOD: MANUAL, OPTIONS: {ALLOW: True, 'bond-master': True, PRE_UP: [PROMISC_ON, IPV6_CFG]}}], 'clhost0': [ {MODES: [DS_IPV4, DS_IPV6], NET: None, FAMILY: INET, METHOD: MANUAL, OPTIONS: {'vlan-raw-device': True, PRE_UP: [VLAN_MOD, VLAN_ADD, DIS_DAD], POST_UP: [SET_MTU, IPV6_CFG], POST_DOWN: [VLAN_DEL]}}, {MODES: [SS_IPV4], NET: constants.NETWORK_TYPE_CLUSTER_HOST, FAMILY: INET, METHOD: STATIC, OPTIONS: {GATEWAY: True, 'vlan-raw-device': True, PRE_UP: [VLAN_MOD, VLAN_ADD, DIS_DAD], POST_UP: [SET_MTU, IPV6_CFG], POST_DOWN: [VLAN_DEL]}}, {MODES: [DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_CLUSTER_HOST, FAMILY: INET, METHOD: STATIC, OPTIONS: {GATEWAY: True, 'vlan-raw-device': True, PRE_UP: [VLAN_MOD], POST_UP: [SET_MTU, IPV6_CFG]}}, {MODES: [SS_IPV6], NET: constants.NETWORK_TYPE_CLUSTER_HOST, FAMILY: INET6, METHOD: STATIC, OPTIONS: {GATEWAY: True, 'vlan-raw-device': True, PRE_UP: [VLAN_MOD, VLAN_ADD, DIS_DAD], POST_UP: [SET_MTU, IPV6_CFG], POST_DOWN: [VLAN_DEL]}}, {MODES: [DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_CLUSTER_HOST, FAMILY: INET6, METHOD: STATIC, OPTIONS: {GATEWAY: True, 'vlan-raw-device': True, PRE_UP: [VLAN_MOD], POST_UP: [SET_MTU, IPV6_CFG, UNDEPR]}}], } self._validate_config(expected) def test_worker_ethernet_pxe_unassigned(self): self._create_host(constants.WORKER) self._add_ethernet('mgmt0', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT) self._add_ethernet('clhost0', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_CLUSTER_HOST) self._add_ethernet('none') expected = { 'mgmt0': [ {NET: None, FAMILY: INET, METHOD: MANUAL, OPTIONS: {POST_UP: [SET_TC, IPV6_CFG]}}, {NET: constants.NETWORK_TYPE_PXEBOOT, FAMILY: INET, METHOD: DHCP, OPTIONS: {POST_UP: [IPV6_CFG]}}, {MODES: [SS_IPV4, DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_MGMT, FAMILY: INET, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG]}}, {MODES: [SS_IPV6, DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_MGMT, FAMILY: INET6, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG, UNDEPR]}}], 'clhost0': [ {MODES: [DS_IPV4, DS_IPV6], NET: None, FAMILY: INET, METHOD: MANUAL, OPTIONS: {POST_UP: [SET_TC, IPV6_CFG]}}, {MODES: [SS_IPV4], NET: constants.NETWORK_TYPE_CLUSTER_HOST, FAMILY: INET, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG]}}, {MODES: [DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_CLUSTER_HOST, FAMILY: INET, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG]}}, {MODES: [SS_IPV6], NET: constants.NETWORK_TYPE_CLUSTER_HOST, FAMILY: INET6, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [SET_TC, IPV6_CFG]}}, {MODES: [DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_CLUSTER_HOST, FAMILY: INET6, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG, UNDEPR]}}], } self._validate_config(expected) def test_worker_ethernet_pxe_with_mgmt(self): self._create_host(constants.WORKER) self._add_ethernet('mgmt0', constants.INTERFACE_CLASS_PLATFORM, [constants.NETWORK_TYPE_MGMT, constants.NETWORK_TYPE_PXEBOOT]) self._add_ethernet('clhost0', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_CLUSTER_HOST) self._add_ethernet('none') expected = { 'mgmt0': [ {NET: None, FAMILY: INET, METHOD: MANUAL, OPTIONS: {POST_UP: [SET_TC, IPV6_CFG]}}, {NET: constants.NETWORK_TYPE_PXEBOOT, FAMILY: INET, METHOD: DHCP, OPTIONS: {POST_UP: [IPV6_CFG]}}, {MODES: [SS_IPV4, DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_MGMT, FAMILY: INET, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG]}}, {MODES: [SS_IPV6, DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_MGMT, FAMILY: INET6, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG, UNDEPR]}}], 'clhost0': [ {MODES: [DS_IPV4, DS_IPV6], NET: None, FAMILY: INET, METHOD: MANUAL, OPTIONS: {POST_UP: [SET_TC, IPV6_CFG]}}, {MODES: [SS_IPV4], NET: constants.NETWORK_TYPE_CLUSTER_HOST, FAMILY: INET, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG]}}, {MODES: [DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_CLUSTER_HOST, FAMILY: INET, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG]}}, {MODES: [SS_IPV6], NET: constants.NETWORK_TYPE_CLUSTER_HOST, FAMILY: INET6, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [SET_TC, IPV6_CFG]}}, {MODES: [DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_CLUSTER_HOST, FAMILY: INET6, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG, UNDEPR]}}], } self._validate_config(expected) def test_worker_ethernet_pxe_with_cluster_host(self): self._create_host(constants.WORKER) self._add_ethernet('mgmt0', constants.INTERFACE_CLASS_PLATFORM, constants.NETWORK_TYPE_MGMT) self._add_ethernet('clhost0', constants.INTERFACE_CLASS_PLATFORM, [constants.NETWORK_TYPE_CLUSTER_HOST, constants.NETWORK_TYPE_PXEBOOT]) self._add_ethernet('none') expected = { 'mgmt0': [ {MODES: [DS_IPV4, DS_IPV6], NET: None, FAMILY: INET, METHOD: MANUAL, OPTIONS: {POST_UP: [SET_TC, IPV6_CFG]}}, {MODES: [SS_IPV4], NET: constants.NETWORK_TYPE_MGMT, FAMILY: INET, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG, SET_TC]}}, {MODES: [DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_MGMT, FAMILY: INET, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG]}}, {MODES: [SS_IPV6], NET: constants.NETWORK_TYPE_MGMT, FAMILY: INET6, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG, SET_TC]}}, {MODES: [DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_MGMT, FAMILY: INET6, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG, UNDEPR]}}], 'clhost0': [ {NET: None, FAMILY: INET, METHOD: MANUAL, OPTIONS: {POST_UP: [SET_TC, IPV6_CFG]}}, {NET: constants.NETWORK_TYPE_PXEBOOT, FAMILY: INET, METHOD: DHCP, OPTIONS: {POST_UP: [IPV6_CFG]}}, {MODES: [SS_IPV4, DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_CLUSTER_HOST, FAMILY: INET, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG]}}, {MODES: [SS_IPV6, DS_IPV4, DS_IPV6], NET: constants.NETWORK_TYPE_CLUSTER_HOST, FAMILY: INET6, METHOD: STATIC, OPTIONS: {GATEWAY: True, POST_UP: [IPV6_CFG, UNDEPR]}}], } self._validate_config(expected) def test_worker_sriov_and_pci_passthrough(self): self._create_host(constants.WORKER) self._add_ethernet('sriov0', constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV) self._add_ethernet('pthru0', constants.INTERFACE_CLASS_PCI_PASSTHROUGH, constants.NETWORK_TYPE_PCI_PASSTHROUGH) expected = { 'sriov0': [ {NET: constants.NETWORK_TYPE_PCI_SRIOV, FAMILY: INET, METHOD: MANUAL, OPTIONS: {PRE_UP: [SRIOV], POST_UP: [IPV6_CFG]}}], 'pthru0': [ {NET: constants.NETWORK_TYPE_PCI_PASSTHROUGH, FAMILY: INET, METHOD: MANUAL, OPTIONS: {PRE_UP: [PTHROUGH], POST_UP: [IPV6_CFG]}}], } self._validate_config(expected) def test_worker_data_over_ethernet(self): self._create_host(constants.WORKER) self._add_ethernet('data0', constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA) self._add_ethernet('slow0', constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA, dpdksupport=False) self._add_ethernet('mlx0', constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA, driver=constants.DRIVER_MLX_CX4) expected = { 'slow0': [ {NET: None, FAMILY: INET, METHOD: MANUAL, OPTIONS: {POST_UP: [IPV6_CFG]}}], 'mlx0': [ {NET: None, FAMILY: INET, METHOD: MANUAL, OPTIONS: {POST_UP: [IPV6_CFG]}}], } self._validate_config(expected) def _get_static_address_args(self, static_enabled, addr_count): families = [self.primary_address_family] if self.secondary_address_family: families.append(self.secondary_address_family) kwargs = {} if constants.IPV4_FAMILY in families: if static_enabled: kwargs['ipv4_mode'] = constants.IPV4_STATIC kwargs['ipv4_addresses'] = addr_count if constants.IPV6_FAMILY in families: if static_enabled: kwargs['ipv6_mode'] = constants.IPV6_STATIC kwargs['ipv6_addresses'] = addr_count return kwargs def test_worker_data_over_ethernet_static_addresses(self): self._create_host(constants.WORKER) system_dict = self.system.as_dict() system_dict['capabilities']['vswitch_type'] = constants.VSWITCH_TYPE_NONE self.dbapi.isystem_update(self.system.uuid, system_dict) self._add_ethernet('data0', constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA) self._add_ethernet('data1', constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA, **self._get_static_address_args(False, 1)) self._add_ethernet('data2', constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA, **self._get_static_address_args(True, 0)) self._add_ethernet('data3', constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA, **self._get_static_address_args(True, 1)) self._add_ethernet('data4', constants.INTERFACE_CLASS_DATA, constants.NETWORK_TYPE_DATA, **self._get_static_address_args(True, 2)) expected = { 'data0': [ {NET: None, FAMILY: INET, METHOD: MANUAL, OPTIONS: {POST_UP: [IPV6_CFG]}}], 'data1': [ {NET: None, FAMILY: INET, METHOD: MANUAL, OPTIONS: {POST_UP: [IPV6_CFG]}}], 'data2': [ {NET: None, FAMILY: INET, METHOD: MANUAL, OPTIONS: {POST_UP: [IPV6_CFG]}}], 'data3': [ {MODES: [DS_IPV4, DS_IPV6], NET: None, FAMILY: INET, METHOD: MANUAL, OPTIONS: {POST_UP: [IPV6_CFG]}}, {MODES: [SS_IPV4, DS_IPV4, DS_IPV6], NET: None, FAMILY: INET, METHOD: STATIC, OPTIONS: {POST_UP: [IPV6_CFG]}}, {MODES: [SS_IPV6, DS_IPV4, DS_IPV6], NET: None, FAMILY: INET6, METHOD: STATIC, OPTIONS: {POST_UP: [IPV6_CFG]}}], 'data4': [ {NET: None, FAMILY: INET, METHOD: MANUAL, OPTIONS: {POST_UP: [IPV6_CFG]}}, {MODES: [SS_IPV4, DS_IPV4, DS_IPV6], NET: None, FAMILY: INET, METHOD: STATIC, OPTIONS: {POST_UP: [IPV6_CFG]}}, {MODES: [SS_IPV4, DS_IPV4, DS_IPV6], NET: None, FAMILY: INET, METHOD: STATIC, OPTIONS: {POST_UP: [IPV6_CFG]}}, {MODES: [SS_IPV6, DS_IPV4, DS_IPV6], NET: None, FAMILY: INET6, METHOD: STATIC, OPTIONS: {POST_UP: [IPV6_CFG]}}, {MODES: [SS_IPV6, DS_IPV4, DS_IPV6], NET: None, FAMILY: INET6, METHOD: STATIC, OPTIONS: {POST_UP: [IPV6_CFG]}}], } self._validate_config(expected) class InterfaceConfigTestIPv4(InterfaceConfigTestMixin, dbbase.BaseHostTestCase): system_mode = SS_IPV4 class InterfaceConfigTestIPv6(InterfaceConfigTestMixin, dbbase.BaseIPv6Mixin, dbbase.BaseHostTestCase): system_mode = SS_IPV6 class InterfaceConfigTestDualStackPrimaryIPv4(InterfaceConfigTestMixin, dbbase.BaseDualStackPrimaryIPv4Mixin, dbbase.BaseHostTestCase): system_mode = DS_IPV4 class InterfaceConfigTestDualStackPrimaryIPv6(InterfaceConfigTestMixin, dbbase.BaseDualStackPrimaryIPv6Mixin, dbbase.BaseHostTestCase): system_mode = DS_IPV6