From c9f23471e31e8a636ca8a1f0e49d329259b29377 Mon Sep 17 00:00:00 2001 From: Teresa Ho Date: Sun, 9 Sep 2018 19:06:01 -0400 Subject: [PATCH] Generalized interface and network configuration - Added the name field to the network table - Removed mtu, link_capacity and vlan_id from the network table - Removed unused networktypes for bm, control and data-vrs - Added four interface classes (platform, data, pci-passthrough, pci-sriov) to interface table - Assign networks to interface during interface creation and modification - Allow infrastructure network and management network to share an interface with or without VLAN. - Updated sysinv puppet for interface and network Story: 2003087 Task: 23171 Depends-On: https://review.openstack.org/#/c/601155 Change-Id: I2e211767639484992f868084eb47baacbe5ea83a Signed-off-by: Teresa Ho --- .../controllerconfig/configassistant.py | 95 ++- .../cgts-client/cgtsclient/v1/iinterface.py | 3 +- .../cgtsclient/v1/iinterface_shell.py | 50 +- .../sysinv/api/controllers/v1/address.py | 28 +- .../sysinv/api/controllers/v1/interface.py | 752 ++++++++++-------- .../api/controllers/v1/network_infra.py | 22 +- .../sysinv/api/controllers/v1/profile.py | 3 +- .../sysinv/sysinv/api/controllers/v1/route.py | 12 +- .../sysinv/api/controllers/v1/system.py | 16 +- .../sysinv/sysinv/sysinv/common/constants.py | 13 +- sysinv/sysinv/sysinv/sysinv/common/utils.py | 36 +- .../sysinv/sysinv/sysinv/conductor/manager.py | 61 +- .../sysinv/sysinv/conductor/openstack.py | 11 +- .../versions/078_interface_class.py | 33 + .../versions/079_network_column_remove.py | 30 + .../sysinv/sysinv/db/sqlalchemy/models.py | 8 +- .../sysinv/sysinv/sysinv/objects/interface.py | 14 +- .../sysinv/sysinv/sysinv/objects/network.py | 3 - .../sysinv/sysinv/objects/network_infra.py | 11 - .../sysinv/sysinv/sysinv/puppet/interface.py | 241 +++--- .../sysinv/sysinv/sysinv/puppet/networking.py | 7 +- sysinv/sysinv/sysinv/sysinv/puppet/neutron.py | 3 +- sysinv/sysinv/sysinv/sysinv/puppet/nova.py | 9 +- .../sysinv/sysinv/sysinv/puppet/platform.py | 32 +- .../sysinv/sysinv/tests/api/test_interface.py | 539 +++++++++---- sysinv/sysinv/sysinv/sysinv/tests/db/utils.py | 31 +- .../sysinv/tests/puppet/test_interface.py | 633 +++++++-------- 27 files changed, 1530 insertions(+), 1166 deletions(-) create mode 100644 sysinv/sysinv/sysinv/sysinv/db/sqlalchemy/migrate_repo/versions/078_interface_class.py create mode 100644 sysinv/sysinv/sysinv/sysinv/db/sqlalchemy/migrate_repo/versions/079_network_column_remove.py diff --git a/controllerconfig/controllerconfig/controllerconfig/configassistant.py b/controllerconfig/controllerconfig/controllerconfig/configassistant.py index 4374e76f2d..45df53be9d 100644 --- a/controllerconfig/controllerconfig/controllerconfig/configassistant.py +++ b/controllerconfig/controllerconfig/controllerconfig/configassistant.py @@ -1443,11 +1443,9 @@ class ConfigAssistant(): user_input == self.external_oam_interface): self.infrastructure_interface = user_input self.infrastructure_interface_name = user_input - if ((self.management_interface_configured and - user_input == self.management_interface) or - (self.external_oam_interface_configured and - user_input == self.external_oam_interface and - not self.external_oam_vlan)): + if (self.external_oam_interface_configured and + user_input == self.external_oam_interface and + not self.external_oam_vlan): infra_vlan_required = True break else: @@ -4007,15 +4005,11 @@ class ConfigAssistant(): # create the network for the pool values = { 'type': sysinv_constants.NETWORK_TYPE_MGMT, - 'mtu': self.management_mtu, - 'link_capacity': self.management_link_capacity, + 'name': sysinv_constants.NETWORK_TYPE_MGMT, 'dynamic': self.dynamic_address_allocation, 'pool_uuid': pool.uuid, } - if self.management_vlan: - values.update({'vlan_id': int(self.management_vlan)}) - client.sysinv.network.create(**values) def _populate_pxeboot_network(self, client): @@ -4032,7 +4026,7 @@ class ConfigAssistant(): # create the network for the pool values = { 'type': sysinv_constants.NETWORK_TYPE_PXEBOOT, - 'mtu': self.management_mtu, + 'name': sysinv_constants.NETWORK_TYPE_PXEBOOT, 'dynamic': True, 'pool_uuid': pool.uuid, } @@ -4055,15 +4049,11 @@ class ConfigAssistant(): # create the network for the pool values = { 'type': sysinv_constants.NETWORK_TYPE_INFRA, - 'mtu': self.infrastructure_mtu, - 'link_capacity': self.infrastructure_link_capacity, + 'name': sysinv_constants.NETWORK_TYPE_INFRA, 'dynamic': self.dynamic_address_allocation, 'pool_uuid': pool.uuid, } - if self.infrastructure_vlan: - values.update({'vlan_id': int(self.infrastructure_vlan)}) - client.sysinv.network.create(**values) def _populate_oam_network(self, client): @@ -4096,14 +4086,11 @@ class ConfigAssistant(): # create the network for the pool values = { 'type': sysinv_constants.NETWORK_TYPE_OAM, - 'mtu': self.external_oam_mtu, + 'name': sysinv_constants.NETWORK_TYPE_OAM, 'dynamic': False, 'pool_uuid': pool.uuid, } - if self.external_oam_vlan: - values.update({'vlan_id': int(self.external_oam_vlan)}) - client.sysinv.network.create(**values) def _populate_multicast_network(self, client): @@ -4120,7 +4107,7 @@ class ConfigAssistant(): # create the network for the pool values = { 'type': sysinv_constants.NETWORK_TYPE_MULTICAST, - 'mtu': self.management_mtu, + 'name': sysinv_constants.NETWORK_TYPE_MULTICAST, 'dynamic': False, 'pool_uuid': pool.uuid, } @@ -4139,7 +4126,7 @@ class ConfigAssistant(): # create the network for the pool values = { 'type': sysinv_constants.NETWORK_TYPE_SYSTEM_CONTROLLER, - 'mtu': '1500', # unused in subcloud + 'name': sysinv_constants.NETWORK_TYPE_SYSTEM_CONTROLLER, 'dynamic': False, 'pool_uuid': pool.uuid, } @@ -4262,6 +4249,14 @@ class ConfigAssistant(): else: raise ConfigFail("Unknown interface AE mode: %s" % aemode) + def _get_network(self, client, network_type): + networks = client.sysinv.network.list() + for net in networks: + if net.type == network_type: + return net + else: + raise ConfigFail("Failed to find network %s" % type) + def _get_interface_mtu(self, ifname): """ This function determines the MTU value that must be configured on an @@ -4295,10 +4290,13 @@ class ConfigAssistant(): def _populate_management_interface(self, client, controller): """Configure the management/pxeboot interface(s)""" + interface_class = sysinv_constants.INTERFACE_CLASS_PLATFORM if self.management_vlan: - networktype = sysinv_constants.NETWORK_TYPE_PXEBOOT + network = self._get_network(client, + sysinv_constants.NETWORK_TYPE_PXEBOOT) else: - networktype = sysinv_constants.NETWORK_TYPE_MGMT + network = self._get_network(client, + sysinv_constants.NETWORK_TYPE_MGMT) if self.lag_management_interface: members = [self.lag_management_interface_member0] @@ -4318,7 +4316,8 @@ class ConfigAssistant(): 'iftype': 'ae', 'aemode': aemode, 'txhashpolicy': txhashpolicy, - 'networktype': networktype, + 'ifclass': interface_class, + 'networks': [str(network.id)], 'uses': members, } @@ -4331,7 +4330,8 @@ class ConfigAssistant(): 'ifname': self.management_interface, 'imtu': self.management_mtu, 'iftype': sysinv_constants.INTERFACE_TYPE_VIRTUAL, - 'networktype': networktype, + 'ifclass': interface_class, + 'networks': [str(network.id)], } client.sysinv.iinterface.create(**values) else: @@ -4340,17 +4340,21 @@ class ConfigAssistant(): 'ihost_uuid': controller.uuid, 'ifname': self.management_interface, 'imtu': self.management_mtu, - 'networktype': networktype, + 'ifclass': interface_class, + 'networks': str(network.id), } self._update_interface_config(client, values) if self.management_vlan: + mgmt_network = self._get_network( + client, sysinv_constants.NETWORK_TYPE_MGMT) values = { 'ihost_uuid': controller.uuid, 'ifname': self.management_interface_name, 'imtu': self.management_mtu, 'iftype': sysinv_constants.INTERFACE_TYPE_VLAN, - 'networktype': sysinv_constants.NETWORK_TYPE_MGMT, + 'ifclass': interface_class, + 'networks': [str(mgmt_network.id)], 'uses': [self.management_interface], 'vlan_id': self.management_vlan, } @@ -4375,10 +4379,9 @@ class ConfigAssistant(): if not self.infrastructure_interface: return # No infrastructure interface configured - if self.infrastructure_vlan: - networktype = sysinv_constants.NETWORK_TYPE_NONE - else: - networktype = sysinv_constants.NETWORK_TYPE_INFRA + interface_class = sysinv_constants.INTERFACE_CLASS_PLATFORM + network = self._get_network(client, + sysinv_constants.NETWORK_TYPE_INFRA) if self.lag_infrastructure_interface: members = [self.lag_infrastructure_interface_member0] @@ -4398,7 +4401,8 @@ class ConfigAssistant(): 'iftype': sysinv_constants.INTERFACE_TYPE_AE, 'aemode': aemode, 'txhashpolicy': txhashpolicy, - 'networktype': networktype, + 'ifclass': interface_class, + 'networks': [str(network.id)], 'uses': members, } @@ -4408,13 +4412,14 @@ class ConfigAssistant(): values = { 'ihost_uuid': controller.uuid, 'ifname': self.infrastructure_interface, + 'ifclass': interface_class, } values.update({ 'imtu': self._get_interface_mtu(self.infrastructure_interface) }) - if networktype != sysinv_constants.NETWORK_TYPE_NONE: + if not self.infrastructure_vlan: values.update({ - 'networktype': networktype + 'networks': str(network.id) }) self._update_interface_config(client, values) @@ -4425,7 +4430,8 @@ class ConfigAssistant(): 'ifname': self.infrastructure_interface_name, 'imtu': self.infrastructure_mtu, 'iftype': sysinv_constants.INTERFACE_TYPE_VLAN, - 'networktype': sysinv_constants.NETWORK_TYPE_INFRA, + 'ifclass': interface_class, + 'networks': [str(network.id)], 'uses': [self.infrastructure_interface], 'vlan_id': self.infrastructure_vlan, } @@ -4434,10 +4440,8 @@ class ConfigAssistant(): def _populate_oam_interface(self, client, controller): """Configure the OAM interface(s)""" - if self.external_oam_vlan: - networktype = sysinv_constants.NETWORK_TYPE_NONE - else: - networktype = sysinv_constants.NETWORK_TYPE_OAM + network = self._get_network(client, + sysinv_constants.NETWORK_TYPE_OAM) if self.lag_external_oam_interface: members = [self.lag_external_oam_interface_member0] @@ -4457,7 +4461,8 @@ class ConfigAssistant(): 'iftype': sysinv_constants.INTERFACE_TYPE_AE, 'aemode': aemode, 'txhashpolicy': txhashpolicy, - 'networktype': networktype, + 'ifclass': sysinv_constants.INTERFACE_CLASS_PLATFORM, + 'networks': [str(network.id)], 'uses': members, } @@ -4467,13 +4472,14 @@ class ConfigAssistant(): values = { 'ihost_uuid': controller.uuid, 'ifname': self.external_oam_interface, + 'ifclass': sysinv_constants.INTERFACE_CLASS_PLATFORM, } values.update({ 'imtu': self._get_interface_mtu(self.external_oam_interface) }) - if networktype != sysinv_constants.NETWORK_TYPE_NONE: + if not self.external_oam_vlan: values.update({ - 'networktype': networktype + 'networks': str(network.id), }) self._update_interface_config(client, values) @@ -4484,7 +4490,8 @@ class ConfigAssistant(): 'ifname': self.external_oam_interface_name, 'imtu': self.external_oam_mtu, 'iftype': sysinv_constants.INTERFACE_TYPE_VLAN, - 'networktype': sysinv_constants.NETWORK_TYPE_OAM, + 'ifclass': sysinv_constants.INTERFACE_CLASS_PLATFORM, + 'networks': [str(network.id)], 'uses': [self.external_oam_interface], 'vlan_id': self.external_oam_vlan, } diff --git a/sysinv/cgts-client/cgts-client/cgtsclient/v1/iinterface.py b/sysinv/cgts-client/cgts-client/cgtsclient/v1/iinterface.py index d69f5a55a3..54f31950c1 100644 --- a/sysinv/cgts-client/cgts-client/cgtsclient/v1/iinterface.py +++ b/sysinv/cgts-client/cgts-client/cgtsclient/v1/iinterface.py @@ -12,7 +12,8 @@ from cgtsclient import exc from cgtsclient.v1 import port -CREATION_ATTRIBUTES = ['ifname', 'iftype', 'ihost_uuid', 'imtu', 'networktype', 'aemode', 'txhashpolicy', +CREATION_ATTRIBUTES = ['ifname', 'iftype', 'ihost_uuid', 'imtu', 'ifclass', + 'networks', 'network_uuid', 'networktype', 'aemode', 'txhashpolicy', 'providernetworks', 'providernetworksdict', 'ifcapabilities', 'ports', 'imac', 'vlan_id', 'uses', 'used_by', 'ipv4_mode', 'ipv6_mode', 'ipv4_pool', 'ipv6_pool', diff --git a/sysinv/cgts-client/cgts-client/cgtsclient/v1/iinterface_shell.py b/sysinv/cgts-client/cgts-client/cgtsclient/v1/iinterface_shell.py index dafe156169..d692684f88 100644 --- a/sysinv/cgts-client/cgts-client/cgtsclient/v1/iinterface_shell.py +++ b/sysinv/cgts-client/cgts-client/cgtsclient/v1/iinterface_shell.py @@ -13,11 +13,12 @@ from cgtsclient.common import utils from cgtsclient import exc from cgtsclient.v1 import ihost as ihost_utils from cgtsclient.v1 import iinterface as iinterface_utils +from cgtsclient.v1 import network as network_utils def _print_iinterface_show(iinterface): - fields = ['ifname', 'networktype', 'iftype', 'ports', 'providernetworks', - 'imac', 'imtu', + fields = ['ifname', 'iftype', 'ports', 'providernetworks', + 'imac', 'imtu', 'ifclass', 'networks', 'aemode', 'schedpolicy', 'txhashpolicy', 'uuid', 'ihost_uuid', 'vlan_id', 'uses', 'used_by', @@ -72,7 +73,7 @@ def do_host_if_list(cc, args): for i in iinterfaces[:]: iinterface_utils._get_ports(cc, ihost, i) if not args.all: - if i.networktype is None and i.used_by == []: + if i.ifclass is None and i.used_by == []: iinterfaces.remove(i) attr_str = "MTU=%s" % i.imtu if i.iftype == 'ae': @@ -80,17 +81,15 @@ def do_host_if_list(cc, args): if i.aemode in ['balanced', '802.3ad']: attr_str = "%s,AE_XMIT_POLICY=%s" % ( attr_str, i.txhashpolicy) - if (i.networktype and - any(network in ['data'] for - network in i.networktype.split(","))): + if i.ifclass and i.ifclass == 'data': if False in i.dpdksupport: attr_str = "%s,accelerated=False" % attr_str else: attr_str = "%s,accelerated=True" % attr_str setattr(i, 'attrs', attr_str) - field_labels = ['uuid', 'name', 'network type', 'type', 'vlan id', 'ports', 'uses i/f', 'used by i/f', 'attributes', 'provider networks'] - fields = ['uuid', 'ifname', 'networktype', 'iftype', 'vlan_id', 'ports', 'uses', 'used_by', 'attrs', 'providernetworks'] + field_labels = ['uuid', 'name', 'class', 'type', 'vlan id', 'ports', 'uses i/f', 'used by i/f', 'attributes', 'provider networks'] + fields = ['uuid', 'ifname', 'ifclass', 'iftype', 'vlan_id', 'ports', 'uses', 'used_by', 'attrs', 'providernetworks'] utils.print_list(iinterfaces, fields, field_labels, sortby=0, no_wrap_fields=['ports']) @@ -146,6 +145,13 @@ def do_host_if_delete(cc, args): const='data', default='data', help='The networktype of the interface (default: %(default)s)') +@utils.arg('-c', '--ifclass', + metavar='', + choices=['platform', 'data', 'pci-passthrough', 'pci-sriov'], + help='The class of the interface') +@utils.arg('--networks', + metavar='', + help="Name or ID of network") @utils.arg('portsorifaces', metavar='', nargs='+', @@ -167,7 +173,8 @@ def do_host_if_delete(cc, args): def do_host_if_add(cc, args): """Add an interface.""" - field_list = ['ifname', 'iftype', 'imtu', 'networktype', 'aemode', + field_list = ['ifname', 'iftype', 'imtu', 'ifclass', 'networks', + 'networktype', 'aemode', 'txhashpolicy', 'providernetworks', 'vlan_id', 'ipv4_mode', 'ipv6_mode', 'ipv4_pool', 'ipv6_pool'] @@ -193,6 +200,9 @@ def do_host_if_add(cc, args): del user_specified_fields['providernetworks'] if 'networktype' in user_specified_fields.keys(): user_specified_fields['networktype'] = user_specified_fields['networktype'].replace(" ", "") + if 'networks' in user_specified_fields.keys(): + network = network_utils._find_network(cc, args.networks) + user_specified_fields['networks'] = [str(network.id)] user_specified_fields['ihost_uuid'] = ihost.uuid user_specified_fields['ports'] = portnamesoruuids @@ -234,6 +244,12 @@ def do_host_if_add(cc, args): @utils.arg('-nt', '--networktype', metavar='', help='The networktype of the interface') +@utils.arg('-c', '--ifclass', + metavar='', + help='The class of the interface') +@utils.arg('--networks', + metavar='', + help="Name or ID of network") @utils.arg('--ipv4-mode', metavar='', choices=['disabled', 'static', 'pool'], @@ -256,7 +272,8 @@ def do_host_if_modify(cc, args): """Modify interface attributes.""" rwfields = ['iftype', 'ifname', 'imtu', 'aemode', 'txhashpolicy', - 'providernetworks', 'ports', 'networktype', + 'providernetworks', 'ports', 'ifclass', 'networktype', + 'networks', 'ipv4_mode', 'ipv6_mode', 'ipv4_pool', 'ipv6_pool', 'sriov_numvfs'] @@ -272,18 +289,21 @@ def do_host_if_modify(cc, args): fields = interface.__dict__ fields.update(user_specified_fields) + if 'networks' in user_specified_fields.keys(): + network = network_utils._find_network(cc, args.networks) + user_specified_fields['networks'] = str(network.id) + # Allow setting an interface back to a None type - if 'networktype' in user_specified_fields.keys(): - user_specified_fields['networktype'] = user_specified_fields['networktype'].replace(" ", "") - if args.networktype == 'none': + if 'ifclass' in user_specified_fields.keys(): + if args.ifclass == 'none': + user_specified_fields['networktype'] = 'none' iinterface_utils._get_ports(cc, ihost, interface) if interface.ports or interface.uses: if interface.iftype != 'ae' and interface.iftype != 'vlan': for p in interface.ports: user_specified_fields['ifname'] = p break - if any(network in ['data'] for - network in interface.networktype.split(",")): + if interface.ifclass == 'data': user_specified_fields['providernetworks'] = 'none' patch = [] diff --git a/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/address.py b/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/address.py index dae9b08fda..c3924023fa 100644 --- a/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/address.py +++ b/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/address.py @@ -46,9 +46,7 @@ LOG = log.getLogger(__name__) ALLOWED_NETWORK_TYPES = [constants.NETWORK_TYPE_MGMT, constants.NETWORK_TYPE_INFRA, constants.NETWORK_TYPE_OAM, - constants.NETWORK_TYPE_DATA, - constants.NETWORK_TYPE_DATA_VRS, - constants.NETWORK_TYPE_CONTROL] + constants.NETWORK_TYPE_DATA] class Address(base.APIBase): @@ -247,12 +245,11 @@ class AddressController(rest.RestController): def _check_interface_type(self, interface_id): interface = pecan.request.dbapi.iinterface_get(interface_id) - networktype = cutils.get_primary_network_type(interface) - if not networktype: + if not interface.networktype: raise exception.InterfaceNetworkTypeNotSet() - if networktype not in ALLOWED_NETWORK_TYPES: + if interface.networktype not in ALLOWED_NETWORK_TYPES: raise exception.UnsupportedInterfaceNetworkType( - networktype=networktype) + networktype=interface.networktype) return def _check_infra_address(self, interface_id, address): @@ -317,17 +314,13 @@ class AddressController(rest.RestController): def _check_address_count(self, interface_id, host_id): interface = pecan.request.dbapi.iinterface_get(interface_id) - networktype = cutils.get_primary_network_type(interface) + networktype = interface['networktype'] sdn_enabled = utils.get_sdn_enabled() if networktype == constants.NETWORK_TYPE_DATA and not sdn_enabled: # Is permitted to add multiple addresses only # if SDN L3 mode is not enabled. return - addresses = ( - pecan.request.dbapi.addresses_get_by_interface(interface_id)) - if len(addresses) != 0: - raise exception.AddressCountLimitedToOne(iftype=networktype) # There can only be one 'data' interface with an IP address # where SDN is enabled @@ -338,8 +331,7 @@ class AddressController(rest.RestController): # skip the one we came in with if uuid == interface_id: continue - nt = cutils.get_primary_network_type(iface) - if nt == constants.NETWORK_TYPE_DATA: + if iface['ifclass'] == constants.NETWORK_TYPE_DATA: addresses = ( pecan.request.dbapi.addresses_get_by_interface(uuid)) if len(addresses) != 0: @@ -385,7 +377,7 @@ class AddressController(rest.RestController): def _check_managed_addr(self, host_id, interface_id): # Check that static address alloc is enabled interface = pecan.request.dbapi.iinterface_get(interface_id) - networktype = cutils.get_primary_network_type(interface) + networktype = interface['networktype'] if networktype not in [constants.NETWORK_TYPE_MGMT, constants.NETWORK_TYPE_INFRA, constants.NETWORK_TYPE_OAM]: @@ -467,8 +459,7 @@ class AddressController(rest.RestController): self._check_interface_type(interface_id) self._check_host_state(host_id) self._check_address_mode(interface_id, address_dict['family']) - if (cutils.get_primary_network_type(interface) == - constants.NETWORK_TYPE_INFRA): + if (interface['networktype'] == constants.NETWORK_TYPE_INFRA): result = self._create_infra_addr( address_dict, host_id, interface_id) else: @@ -527,8 +518,7 @@ class AddressController(rest.RestController): self._check_host_state(getattr(address, 'forihostid')) self._check_from_pool(getattr(address, 'pool_uuid')) interface = pecan.request.dbapi.iinterface_get(interface_uuid) - if (cutils.get_primary_network_type(interface) == - constants.NETWORK_TYPE_INFRA): + if (interface['networktype'] == constants.NETWORK_TYPE_INFRA): self._delete_infra_addr(address) else: pecan.request.dbapi.address_destroy(address_uuid) diff --git a/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/interface.py b/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/interface.py index 2bf3de169c..90bdd563c0 100644 --- a/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/interface.py +++ b/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/interface.py @@ -41,7 +41,7 @@ from sysinv.api.controllers.v1 import link from sysinv.api.controllers.v1 import route from sysinv.api.controllers.v1 import types from sysinv.api.controllers.v1 import utils -from sysinv.api.controllers.v1 import network +from sysinv.api.controllers.v1 import interface_network from sysinv.common import constants from sysinv.common import exception from sysinv.common import utils as cutils @@ -58,7 +58,6 @@ LOG = log.getLogger(__name__) FM = fm_api.FaultAPIs() - # These are the only valid network type values VALID_NETWORK_TYPES = [constants.NETWORK_TYPE_NONE, constants.NETWORK_TYPE_PXEBOOT, @@ -66,16 +65,23 @@ VALID_NETWORK_TYPES = [constants.NETWORK_TYPE_NONE, constants.NETWORK_TYPE_MGMT, constants.NETWORK_TYPE_INFRA, constants.NETWORK_TYPE_DATA, - constants.NETWORK_TYPE_DATA_VRS, constants.NETWORK_TYPE_PCI_PASSTHROUGH, - constants.NETWORK_TYPE_PCI_SRIOV, - constants.NETWORK_TYPE_CONTROL] + constants.NETWORK_TYPE_PCI_SRIOV] + +VALID_INTERFACE_CLASS = [constants.INTERFACE_CLASS_PLATFORM, + constants.INTERFACE_CLASS_DATA, + constants.INTERFACE_CLASS_PCI_PASSTHROUGH, + constants.INTERFACE_CLASS_PCI_SRIOV] # Interface network types that require coordination with neutron NEUTRON_NETWORK_TYPES = [constants.NETWORK_TYPE_DATA, constants.NETWORK_TYPE_PCI_PASSTHROUGH, constants.NETWORK_TYPE_PCI_SRIOV] +NEUTRON_INTERFACE_CLASS = [constants.INTERFACE_CLASS_DATA, + constants.INTERFACE_CLASS_PCI_PASSTHROUGH, + constants.INTERFACE_CLASS_PCI_SRIOV] + # Interface network types that are PCI based PCI_NETWORK_TYPES = [constants.NETWORK_TYPE_PCI_PASSTHROUGH, constants.NETWORK_TYPE_PCI_SRIOV] @@ -101,7 +107,6 @@ DEFAULT_MTU = 1500 class InterfacePatchType(types.JsonPatchType): - @staticmethod def mandatory_attrs(): return ['/address', '/ihost_uuid'] @@ -119,43 +124,46 @@ class Interface(base.APIBase): "Unique UUID for this interface" ifname = wtypes.text - "Represent the unique name of the iinterface" + "Represent the unique name of the interface" iftype = wtypes.text - "Represent the unique type of the iinterface" + "Represent the unique type of the interface" # mac = wsme.wsattr(types.macaddress, mandatory=True) imac = wsme.wsattr(types.macaddress, mandatory=False) - "MAC Address for this iinterface" + "MAC Address for this interface" imtu = int - "MTU bytes size for this iinterface" + "MTU bytes size for this interface" + + ifclass = wtypes.text + "Represent the class of the interface" networktype = wtypes.text - "Represent the network type of the iinterface" + "Represent the network type of the interface" aemode = wtypes.text - "Represent the aemode of the iinterface" + "Represent the aemode of the interface" schedpolicy = wtypes.text - "Represent the schedpolicy of the iinterface" + "Represent the schedpolicy of the interface" txhashpolicy = wtypes.text - "Represent the txhashpolicy of the iinterface" + "Represent the txhashpolicy of the interface" providernetworks = wtypes.text - "Represent the providernetworks of the iinterface" + "Represent the providernetworks of the interface" providernetworksdict = {wtypes.text: utils.ValidTypes(wtypes.text, - six.integer_types)} - "Represent the providernetworksdict of the iinterface" + six.integer_types)} + "Represent the providernetworksdict of the interface" ifcapabilities = {wtypes.text: utils.ValidTypes(wtypes.text, - six.integer_types)} + six.integer_types)} "This interface's meta data" forihostid = int - "The ihostid that this iinterface belongs to" + "The ihostid that this interface belongs to" ihost_uuid = types.uuid "The UUID of the host this interface belongs to" @@ -167,7 +175,7 @@ class Interface(base.APIBase): "A list containing a self link and associated interface links" vlan_id = int - "VLAN id for this iinterface" + "VLAN id for this interface" uses = [wtypes.text] "A list containing the interface(s) that this interface uses" @@ -193,6 +201,9 @@ class Interface(base.APIBase): sriov_numvfs = int "The number of configured SR-IOV VFs" + networks = [wtypes.text] + "Represent the networks of the interface" + def __init__(self, **kwargs): self.fields = objects.interface.fields.keys() for k in self.fields: @@ -210,22 +221,23 @@ class Interface(base.APIBase): interface = Interface(**rpc_interface.as_dict()) if not expand: interface.unset_fields_except(['uuid', 'ifname', 'iftype', - 'imac', 'imtu', 'networktype', 'aemode', - 'schedpolicy', 'txhashpolicy', - 'providernetworks', 'ihost_uuid', 'forihostid', - 'vlan_id', 'uses', 'usesmodify', 'used_by', - 'ipv4_mode', 'ipv6_mode', 'ipv4_pool', 'ipv6_pool', - 'sriov_numvfs']) + 'imac', 'imtu', 'ifclass', 'networktype', 'networks', + 'aemode', 'schedpolicy', 'txhashpolicy', + 'providernetworks', 'ihost_uuid', 'forihostid', + 'vlan_id', 'uses', 'usesmodify', 'used_by', + 'ipv4_mode', 'ipv6_mode', 'ipv4_pool', 'ipv6_pool', + 'sriov_numvfs']) # never expose the ihost_id attribute interface.ihost_id = wtypes.Unset + # interface.networktype = wtypes.Unset interface.links = [link.Link.make_link('self', pecan.request.host_url, - 'iinterfaces', interface.uuid), - link.Link.make_link('bookmark', - pecan.request.host_url, - 'iinterfaces', interface.uuid, - bookmark=True) + 'iinterfaces', interface.uuid), + link.Link.make_link('bookmark', + pecan.request.host_url, + 'iinterfaces', interface.uuid, + bookmark=True) ] if expand: interface.ports = [ @@ -241,8 +253,20 @@ class Interface(base.APIBase): bookmark=True) ] - networktype = cutils.get_primary_network_type(rpc_interface.as_dict()) - if networktype and networktype not in address.ALLOWED_NETWORK_TYPES: + ifclass = rpc_interface.as_dict()['ifclass'] + networks = rpc_interface.as_dict()['networks'] + networktypelist = [] + if ifclass == constants.INTERFACE_CLASS_PLATFORM: + for network_id in networks: + network = pecan.request.dbapi.network_get_by_id(network_id) + networktypelist.append(network.type) + elif ifclass: + networktypelist.append(ifclass) + else: + networktypelist.append(constants.INTERFACE_CLASS_NONE) + if not any(networktype in address.ALLOWED_NETWORK_TYPES + for networktype in networktypelist): + # Hide this functionality when the network type does not support # setting or updating the network type interface.ipv4_mode = wtypes.Unset @@ -294,6 +318,10 @@ class InterfaceController(rest.RestController): routes = route.RouteController(parent="iinterfaces") "Expose routes as a sub-element of interface" + interface_networks = interface_network.InterfaceNetworkController( + parent="iinterfaces") + "Expose interface_networks as a sub-element of interface" + _custom_actions = { 'detail': ['GET'], } @@ -305,7 +333,7 @@ class InterfaceController(rest.RestController): sort_dir, expand=False, resource_url=None): if self._from_ihosts and not ihost_uuid: raise exception.InvalidParameterValue(_( - "Host id not specified.")) + "Host id not specified.")) limit = utils.validate_limit(limit) sort_dir = utils.validate_sort_dir(sort_dir) @@ -313,20 +341,20 @@ class InterfaceController(rest.RestController): marker_obj = None if marker: marker_obj = objects.interface.get_by_uuid( - pecan.request.context, - marker) + pecan.request.context, + marker) if ihost_uuid: interfaces = pecan.request.dbapi.iinterface_get_by_ihost( - ihost_uuid, limit, - marker_obj, - sort_key=sort_key, - sort_dir=sort_dir) + ihost_uuid, limit, + marker_obj, + sort_key=sort_key, + sort_dir=sort_dir) else: interfaces = pecan.request.dbapi.iinterface_get_list( - limit, marker_obj, - sort_key=sort_key, - sort_dir=sort_dir) + limit, marker_obj, + sort_key=sort_key, + sort_dir=sort_dir) return InterfaceCollection.convert_with_links(interfaces, limit, url=resource_url, @@ -355,7 +383,7 @@ class InterfaceController(rest.RestController): @wsme_pecan.wsexpose(InterfaceCollection, types.uuid, types.uuid, int, wtypes.text, wtypes.text) def detail(self, ihost_uuid=None, marker=None, limit=None, - sort_key='id', sort_dir='asc'): + sort_key='id', sort_dir='asc'): """Retrieve a list of interfaces with detail.""" # NOTE(lucasagomes): /detail should only work agaist collections parent = pecan.request.path.split('/')[:-1][-1] @@ -376,7 +404,7 @@ class InterfaceController(rest.RestController): raise exception.OperationNotPermitted rpc_interface = objects.interface.get_by_uuid( - pecan.request.context, interface_uuid) + pecan.request.context, interface_uuid) return Interface.convert_with_links(rpc_interface) @cutils.synchronized(LOCK_NAME) @@ -409,26 +437,38 @@ class InterfaceController(rest.RestController): LOG.debug("patch_data: %s" % patch) uses = None + ports = None + networks = [] + networks_to_add = [] + patches_to_remove = [] for p in patch: - if '/usesmodify' in p['path']: + if '/ifclass' == p['path']: + if p['value'] == 'none': + p['value'] = None + elif '/usesmodify' == p['path']: uses = p['value'].split(',') - patch.remove(p) - break + patches_to_remove.append(p) + elif '/ports' == p['path']: + ports = p['value'] + patches_to_remove.append(p) + elif '/networks' == p['path']: + networks = p['value'].split(',') + patches_to_remove.append(p) + elif '/networks_to_add' == p['path']: + networks_to_add = p['value'].split(',') + patches_to_remove.append(p) if uses: patch.append(dict(path='/uses', value=uses, op='replace')) - ports = None - for p in patch: - if '/ports' in p['path']: - ports = p['value'] - patch.remove(p) - break + patch = [p for p in patch if p not in patches_to_remove] LOG.debug("patch_ports: %s" % ports) + LOG.debug("patch_networks: %s" % networks) rpc_interface = objects.interface.get_by_uuid(pecan.request.context, interface_uuid) + # create a temp interface for semantics checks temp_interface = copy.deepcopy(rpc_interface) @@ -461,8 +501,9 @@ class InterfaceController(rest.RestController): temp_interface['sriov_numvfs'] = p['value'] # If network type is not pci-sriov, reset the sriov-numvfs to zero if (temp_interface['sriov_numvfs'] is not None and - temp_interface['networktype'] is not None and - constants.NETWORK_TYPE_PCI_SRIOV not in temp_interface['networktype']): + temp_interface['ifclass'] is not None and + temp_interface[ + 'ifclass'] != constants.INTERFACE_CLASS_PCI_SRIOV): temp_interface['sriov_numvfs'] = None _check_interface_sriov(temp_interface.as_dict(), ihost) @@ -500,8 +541,8 @@ class InterfaceController(rest.RestController): try: interface = Interface(**jsonpatch.apply_patch( - rpc_interface.as_dict(), - patch_obj)).as_dict() + rpc_interface.as_dict(), + patch_obj)).as_dict() except utils.JSONPATCH_EXCEPTIONS as e: raise exception.PatchError(patch=patch, reason=e) @@ -509,9 +550,14 @@ class InterfaceController(rest.RestController): if interface['aemode'] == 'active_standby': interface['txhashpolicy'] = None - if (not interface['networktype'] or - interface['networktype'] == constants.NETWORK_TYPE_NONE): - # If the interface networktype is reset, make sure any networktype + # The variable 'networks' contains a list of networks that the + # interface should have by the end of this update. These should be + # compared to the previous networks assigned to the interface + interface['networks'] = networks + + if (not interface['ifclass'] or + interface['ifclass'] == constants.INTERFACE_CLASS_NONE): + # If the interface class is reset, make sure any network # specific fields are reset as well interface['sriov_numvfs'] = 0 interface['ipv4_mode'] = None @@ -539,26 +585,32 @@ class InterfaceController(rest.RestController): if ports: _update_ports("modify", rpc_interface, ihost, ports) - networktype = cutils.get_primary_network_type(interface) - orig_networktype = cutils.get_primary_network_type(rpc_interface) - if ((not networktype) and - orig_networktype == constants.NETWORK_TYPE_MGMT): - # Remove mgmt address associated with this interface - pecan.request.rpcapi.mgmt_ip_set_by_ihost( - pecan.request.context, - ihost['uuid'], - None) - if ((not networktype) and - orig_networktype == constants.NETWORK_TYPE_INFRA): - # Remove infra address associated with this interface - pecan.request.rpcapi.infra_ip_set_by_ihost( - pecan.request.context, - ihost['uuid'], - None) + if (not interface['ifclass'] or + interface['ifclass'] == constants.NETWORK_TYPE_NONE): + ifclass = None + else: + ifclass = interface['ifclass'] + orig_ifclass = rpc_interface['ifclass'] + if (not ifclass and + orig_ifclass == constants.INTERFACE_CLASS_PLATFORM): + for network_id in rpc_interface['networks']: + network = pecan.request.dbapi.network_get_by_id(network_id) + if network.type == constants.NETWORK_TYPE_MGMT: + # Remove mgmt address associated with this interface + pecan.request.rpcapi.mgmt_ip_set_by_ihost( + pecan.request.context, + ihost['uuid'], + None) + elif network.type == constants.NETWORK_TYPE_INFRA: + # Remove infra address associated with this interface + pecan.request.rpcapi.infra_ip_set_by_ihost( + pecan.request.context, + ihost['uuid'], + None) if delete_addressing: for family in constants.IP_FAMILIES: - _delete_addressing(interface, family, orig_networktype) + _delete_addressing(interface, family, rpc_interface) else: if _is_ipv4_address_mode_updated(interface, rpc_interface): _update_ipv4_address_mode(interface) @@ -566,17 +618,35 @@ class InterfaceController(rest.RestController): _update_ipv6_address_mode(interface) # Commit operation with neutron - if (interface['networktype'] and - any(network.strip() in NEUTRON_NETWORK_TYPES for network in - interface['networktype'].split(","))): + if (interface['ifclass'] and + interface['ifclass'] in NEUTRON_INTERFACE_CLASS): _neutron_bind_interface(ihost, interface) - elif (rpc_interface['networktype'] and - any(network.strip() in NEUTRON_NETWORK_TYPES for network in - rpc_interface['networktype'].split(","))): + elif (rpc_interface['ifclass'] and + interface['ifclass'] in NEUTRON_INTERFACE_CLASS): _neutron_unbind_interface(ihost, rpc_interface) saved_interface = copy.deepcopy(rpc_interface) + # Update network-interface + try: + if networks_to_add: + for network_id in networks_to_add: + values = {'interface_id': interface['id'], + 'network_id': network_id} + pecan.request.dbapi.interface_network_create(values) + elif networks: + for network_id in networks: + values = {'interface_id': interface['id'], + 'network_id': network_id} + pecan.request.dbapi.interface_network_create(values) + except exception.InterfaceNetworkAlreadyExists: + pass + except Exception as e: + LOG.exception(e) + msg = _("Failed to create interface network association for " + "interface %s" % (interface['ifname'])) + raise wsme.exc.ClientSideError(msg) + try: # Update only the fields that have changed for field in objects.interface.fields: @@ -589,15 +659,25 @@ class InterfaceController(rest.RestController): new_interface = objects.interface.get_by_uuid( pecan.request.context, rpc_interface.uuid) + networktypelist = [] + if new_interface['ifclass'] == constants.INTERFACE_CLASS_PLATFORM: + for network_id in new_interface['networks']: + network = pecan.request.dbapi.network_get_by_id(network_id) + networktypelist.append(network.type) + elif new_interface['ifclass']: + networktypelist = [new_interface['ifclass']] + else: + networktypelist = [constants.NETWORK_TYPE_NONE] + # Update address (if required) - if networktype == constants.NETWORK_TYPE_MGMT: + if constants.NETWORK_TYPE_MGMT in networktypelist: _update_host_mgmt_address(ihost, interface) - elif networktype == constants.NETWORK_TYPE_INFRA: + if constants.NETWORK_TYPE_INFRA in networktypelist: _update_host_infra_address(ihost, interface) if ihost['personality'] == constants.CONTROLLER: - if networktype == constants.NETWORK_TYPE_OAM: + if constants.NETWORK_TYPE_OAM in networktypelist: _update_host_oam_address(ihost, interface) - elif networktype == constants.NETWORK_TYPE_PXEBOOT: + elif constants.NETWORK_TYPE_PXEBOOT in networktypelist: _update_host_pxeboot_address(ihost, interface) # Update the MTU of underlying interfaces of an AE @@ -620,9 +700,8 @@ class InterfaceController(rest.RestController): LOG.exception(e) msg = _("Interface update failed: host %s if %s : patch %s" % (ihost['hostname'], interface['ifname'], patch)) - if (saved_interface['networktype'] and - any(network.strip() in NEUTRON_NETWORK_TYPES for network in - saved_interface['networktype'].split(","))): + if (saved_interface['ifclass'] and + saved_interface['ifclass'] in NEUTRON_INTERFACE_CLASS): # Restore Neutron bindings _neutron_bind_interface(ihost, saved_interface) @@ -674,9 +753,20 @@ def _set_defaults(interface): 'vlan_id': None, 'sriov_numvfs': 0} - networktype = cutils.get_primary_network_type(interface) - if networktype in [constants.NETWORK_TYPE_DATA, - constants.NETWORK_TYPE_DATA_VRS]: + if interface['ifclass'] == constants.INTERFACE_CLASS_PLATFORM: + if interface['networks']: + for network_id in interface['networks']: + network = pecan.request.dbapi.network_get_by_id(network_id) + interface['networktype'] = network.type + break + elif interface['networktype']: + network = pecan.request.dbapi.network_get_by_type( + interface['networktype'] + ) + interface['networks'] = [str(network.id)] + + networktype = interface['networktype'] + if interface['ifclass'] == constants.INTERFACE_CLASS_DATA: defaults['ipv4_mode'] = constants.IPV4_DISABLED defaults['ipv6_mode'] = constants.IPV6_DISABLED elif (networktype == constants.NETWORK_TYPE_MGMT or @@ -684,15 +774,6 @@ def _set_defaults(interface): networktype == constants.NETWORK_TYPE_INFRA): _set_address_family_defaults_by_pool(defaults, networktype) - # Update default MTU to that of configured network - if networktype in network.ALLOWED_NETWORK_TYPES: - try: - interface_network = pecan.request.dbapi.network_get_by_type( - networktype) - defaults['imtu'] = interface_network.mtu - except exception.NetworkTypeNotFound: - pass # use default MTU - interface_merged = interface.copy() for key in interface_merged: if interface_merged[key] is None and key in defaults: @@ -706,26 +787,6 @@ def _check_interface_vlan_id(op, interface, ihost, from_profile=False): if 'vlan_id' in interface.keys() and interface['vlan_id'] is not None: if not str(interface['vlan_id']).isdigit(): raise wsme.exc.ClientSideError(_("VLAN id is an integer value.")) - elif not from_profile: - networktype = [] - if interface['networktype']: - networktype = [network.strip() for network in interface['networktype'].split(",")] - if (any(network in [constants.NETWORK_TYPE_MGMT] for network in networktype) and - ihost['recordtype'] != 'profile'): - - mgmt_network = pecan.request.dbapi.network_get_by_type( - constants.NETWORK_TYPE_MGMT) - if not mgmt_network.vlan_id: - msg = _("The management VLAN was not configured on this " - "system, so configuring the %s interface over a VLAN " - "is not allowed." % (interface['networktype'])) - raise wsme.exc.ClientSideError(msg) - elif int(interface['vlan_id']) != int(mgmt_network.vlan_id): - msg = _("The management VLAN configured on this " - "system is %s, so the VLAN configured for the %s " - "interface must match." % (mgmt_network.vlan_id, - interface['networktype'])) - raise wsme.exc.ClientSideError(msg) interface['vlan_id'] = int(interface['vlan_id']) if interface['vlan_id'] < 1 or interface['vlan_id'] > 4094: @@ -757,7 +818,7 @@ def _check_interface_name(op, interface, ihost, from_profile=False): if ifname and len(ifname) > iflen: raise wsme.exc.ClientSideError(_("Interface {} has name length " "greater than {}.". - format(ifname, iflen))) + format(ifname, iflen))) # Check for invalid characters vlan_id = None @@ -777,7 +838,7 @@ def _check_interface_name(op, interface, ihost, from_profile=False): else: this_interface_id = interface['id'] interface_list = pecan.request.dbapi.iinterface_get_all( - forihostid=ihost_id) + forihostid=ihost_id) for i in interface_list: if i.id == this_interface_id: continue @@ -791,15 +852,6 @@ def _check_interface_mtu(interface, ihost, from_profile=False): if 'imtu' in interface.keys() and interface['imtu'] is not None: if not str(interface['imtu']).isdigit(): raise wsme.exc.ClientSideError(_("MTU is an integer value.")) - elif not from_profile and ihost['recordtype'] != 'profile': - networktype = cutils.get_primary_network_type(interface) - if networktype in [constants.NETWORK_TYPE_MGMT, - constants.NETWORK_TYPE_INFRA]: - network = pecan.request.dbapi.network_get_by_type(networktype) - if network and int(interface['imtu']) != int(network.mtu): - msg = _("Setting of %s interface MTU is not supported" - % networktype) - raise wsme.exc.ClientSideError(msg) interface['imtu'] = int(interface['imtu']) utils.validate_mtu(interface['imtu']) @@ -807,28 +859,25 @@ def _check_interface_mtu(interface, ihost, from_profile=False): def _check_interface_sriov(interface, ihost, from_profile=False): - if 'networktype' in interface.keys() and interface['networktype'] == constants.NETWORK_TYPE_NONE: + if ('ifclass' in interface.keys() and + interface['ifclass'] == constants.INTERFACE_CLASS_NONE): return interface - networktypelist = cutils.get_network_type_list(interface) - if ('networktype' in interface.keys() and - constants.NETWORK_TYPE_PCI_SRIOV in networktypelist and - 'sriov_numvfs' not in interface.keys()): - + if (interface['ifclass'] == constants.INTERFACE_CLASS_PCI_SRIOV and + 'sriov_numvfs' not in interface.keys()): raise wsme.exc.ClientSideError(_("A network type of pci-sriov must specify " - "a number for SR-IOV VFs.")) + "a number for SR-IOV VFs.")) if ('sriov_numvfs' in interface.keys() and interface['sriov_numvfs'] - is not None and int(interface['sriov_numvfs']) > 0 and - ('networktype' not in interface.keys() or - constants.NETWORK_TYPE_PCI_SRIOV not in interface['networktype'])): - + is not None and int(interface['sriov_numvfs']) > 0 and + ('ifclass' not in interface.keys() or + interface['ifclass'] == constants.INTERFACE_CLASS_PCI_SRIOV)): raise wsme.exc.ClientSideError(_("Number of SR-IOV VFs is specified but network " - "type is not pci-sriov.")) + "type is not pci-sriov.")) - if ('networktype' in interface.keys() and - constants.NETWORK_TYPE_PCI_SRIOV in networktypelist and - 'sriov_numvfs' in interface.keys()): + if ('ifclass' in interface.keys() and + interface['ifclass'] == constants.INTERFACE_CLASS_PCI_SRIOV and + 'sriov_numvfs' in interface.keys()): if interface['sriov_numvfs'] is None: raise wsme.exc.ClientSideError(_("Value for number of SR-IOV VFs must be specified.")) @@ -864,7 +913,7 @@ def _check_interface_sriov(interface, ihost, from_profile=False): def _check_host(ihost): if utils.is_aio_simplex_host_unlocked(ihost): - raise wsme.exc.ClientSideError(_("Host must be locked.")) + raise wsme.exc.ClientSideError(_("Host must be locked.")) elif ihost['administrative'] != 'locked' and not \ utils.is_host_simplex_controller(ihost): unlocked = False @@ -878,11 +927,8 @@ def _check_host(ihost): def _valid_network_types(): valid_types = set(VALID_NETWORK_TYPES) - vswitch_type = utils.get_vswitch_type() system_mode = utils.get_system_mode() - if vswitch_type != constants.VSWITCH_TYPE_NUAGE_VRS: - valid_types -= set([constants.NETWORK_TYPE_DATA_VRS]) if system_mode == constants.SYSTEM_MODE_SIMPLEX: valid_types -= set([constants.NETWORK_TYPE_INFRA]) return list(valid_types) @@ -895,25 +941,16 @@ def _check_network_type_validity(networktypelist): raise wsme.exc.ClientSideError(msg) -def _check_network_type_count(networktypelist): - if (networktypelist and len(networktypelist) != 1 and - not cutils.is_pci_network_types(networktypelist)): - msg = _("Network type list may only contain at most one type, " - "except for PCI network types.") - raise wsme.exc.ClientSideError(msg) - - def _check_network_type_and_host_type(ihost, networktypelist): - for nt in DATA_NETWORK_TYPES: if (nt in networktypelist and - constants.COMPUTE not in ihost['subfunctions']): + constants.COMPUTE not in ihost['subfunctions']): msg = _("The '%s' network type is only supported on nodes " - "supporting compute functions" % nt) + "supporting compute functions" % nt) raise wsme.exc.ClientSideError(msg) if (constants.NETWORK_TYPE_OAM in networktypelist and - ihost['personality'] != constants.CONTROLLER): + ihost['personality'] != constants.CONTROLLER): msg = _("The '%s' network type is only supported on controller nodes." % constants.NETWORK_TYPE_OAM) raise wsme.exc.ClientSideError(msg) @@ -934,30 +971,23 @@ def _check_network_type_and_interface_type(interface, networktypelist): if (any(nt in networktypelist for nt in PCI_NETWORK_TYPES) and interface['iftype'] != "ethernet"): - msg = (_("The {} network types are only valid on Ethernet interfaces"). format(', '.join(PCI_NETWORK_TYPES))) raise wsme.exc.ClientSideError(msg) - if (constants.NETWORK_TYPE_DATA_VRS in networktypelist and - interface['iftype'] not in ['ethernet', 'ae']): - msg = _("Only ethernet and aggregated ethernet interfaces can be " - "configured as '%s' interfaces" % - constants.NETWORK_TYPE_DATA_VRS) - raise wsme.exc.ClientSideError(msg) - def _check_network_type_duplicates(ihost, interface, networktypelist): # Check that we are not creating duplicate interface types interfaces = pecan.request.dbapi.iinterface_get_by_ihost(ihost['uuid']) for host_interface in interfaces: - if not host_interface['networktype']: + if not host_interface['networks']: continue - host_networktypes = host_interface['networktype'] - host_networktypelist = [ - nt.strip() for nt in host_networktypes.split(",")] + host_networktypelist = [] + for network_id in host_interface['networks']: + network = pecan.request.dbapi.network_get_by_id(network_id) + host_networktypelist.append(network.type) - for nt in [constants.NETWORK_TYPE_INFRA, constants.NETWORK_TYPE_MGMT, constants.NETWORK_TYPE_OAM, constants.NETWORK_TYPE_DATA_VRS]: + for nt in [constants.NETWORK_TYPE_INFRA, constants.NETWORK_TYPE_MGMT, constants.NETWORK_TYPE_OAM]: if nt in host_networktypelist and nt in networktypelist: if host_interface['uuid'] != interface['uuid']: msg = _("An interface with '%s' network type is " @@ -965,29 +995,24 @@ def _check_network_type_duplicates(ihost, interface, networktypelist): raise wsme.exc.ClientSideError(msg) -def _check_network_type_transition(interface, existing_interface): +def _check_interface_class_transition(interface, existing_interface): if not existing_interface: return - networktype = cutils.get_primary_network_type(interface) - existing_networktype = cutils.get_primary_network_type(existing_interface) - if networktype == existing_networktype: - if networktype == constants.NETWORK_TYPE_PCI_SRIOV: + ifclass = interface['ifclass'] + existing_ifclass = existing_interface['ifclass'] + if ifclass == existing_ifclass: + if ifclass == constants.NETWORK_TYPE_PCI_SRIOV: if (len(cutils.get_network_type_list(interface)) == len(cutils.get_network_type_list(existing_interface))): return else: return - if networktype and existing_networktype: - msg = _("The network type of an interface cannot be changed without " - "first being reset back to '%s'." % - constants.NETWORK_TYPE_NONE) - raise wsme.exc.ClientSideError(msg) def _check_network_type_and_interface_name(interface, networktypelist): if (utils.get_system_mode() == constants.SYSTEM_MODE_SIMPLEX and - constants.NETWORK_TYPE_NONE in networktypelist and - interface['ifname'] == constants.LOOPBACK_IFNAME): + constants.NETWORK_TYPE_NONE in networktypelist and + interface['ifname'] == constants.LOOPBACK_IFNAME): msg = _("The loopback interface cannot be changed for an all-in-one " "simplex system") raise wsme.exc.ClientSideError(msg) @@ -995,13 +1020,17 @@ def _check_network_type_and_interface_name(interface, networktypelist): def _check_network_type(op, interface, ihost, existing_interface): networktypelist = [] - if interface['networktype']: - networktypelist = [ - nt.strip() for nt in interface['networktype'].split(",")] + if interface['ifclass'] == constants.INTERFACE_CLASS_PLATFORM: + for network_id in interface['networks']: + network = pecan.request.dbapi.network_get_by_id(network_id) + networktypelist.append(network.type) + elif interface['ifclass']: + networktypelist.append(interface['ifclass']) + else: + networktypelist.append(constants.INTERFACE_CLASS_NONE) _check_network_type_validity(networktypelist) - _check_network_type_transition(interface, existing_interface) - _check_network_type_count(networktypelist) + _check_interface_class_transition(interface, existing_interface) _check_network_type_and_host_type(ihost, networktypelist) _check_network_type_and_interface_type(interface, networktypelist) _check_network_type_duplicates(ihost, interface, networktypelist) @@ -1030,9 +1059,9 @@ def _check_network_type_and_port(interface, ihost, pif_networktypelist = cutils.get_network_type_list(pif) if (pif_networktypelist and ((constants.NETWORK_TYPE_DATA in pif_networktypelist and - constants.NETWORK_TYPE_DATA not in networktypelist) or - (constants.NETWORK_TYPE_DATA not in pif_networktypelist and - constants.NETWORK_TYPE_DATA in networktypelist))): + constants.NETWORK_TYPE_DATA not in networktypelist) or + (constants.NETWORK_TYPE_DATA not in pif_networktypelist and + constants.NETWORK_TYPE_DATA in networktypelist))): msg = (_("Shared device %(device)s cannot be shared " "with different network types when device " "is associated with a data network type") % @@ -1040,6 +1069,27 @@ def _check_network_type_and_port(interface, ihost, raise wsme.exc.ClientSideError(msg) +def _check_interface_class(interface, existing_interface): + if not interface['ifclass'] or interface['ifclass'] == constants.INTERFACE_CLASS_NONE: + return + + if interface['ifclass'] not in VALID_INTERFACE_CLASS: + msg = (_("Invalid interface class %s" % interface['ifclass'])) + raise wsme.exc.ClientSideError(msg) + + if interface['ifclass'] == constants.INTERFACE_CLASS_PLATFORM: + for network_id in interface['networks']: + network = pecan.request.dbapi.network_get_by_id(network_id) + if network.type not in constants.PLATFORM_NETWORK_TYPES: + msg = (_("Invalid network type %s for interface class %s" % + (network.type, interface['ifclass']))) + raise wsme.exc.ClientSideError(msg) + + if existing_interface and existing_interface['ifclass']: + if existing_interface['ifclass'] == interface['ifclass']: + return + + def _check_address_mode(op, interface, ihost, existing_interface): # Check for valid values: interface_id = interface['id'] @@ -1049,8 +1099,18 @@ def _check_address_mode(op, interface, ihost, existing_interface): object_utils.ipv6_mode_or_none(ipv6_mode) # Check for supported interface network types - network_type = cutils.get_primary_network_type(interface) - if network_type not in address.ALLOWED_NETWORK_TYPES: + networktypelist = [] + if interface['ifclass'] == constants.INTERFACE_CLASS_PLATFORM: + for network_id in interface['networks']: + network = pecan.request.dbapi.network_get_by_id(network_id) + networktypelist.append(network.type) + elif interface['ifclass']: + networktypelist.append(interface['ifclass']) + else: + networktypelist.append(constants.INTERFACE_CLASS_NONE) + + if not any(network_type in address.ALLOWED_NETWORK_TYPES + for network_type in networktypelist): if (ipv4_mode and ipv4_mode != constants.IPV4_DISABLED): raise exception.AddressModeOnlyOnSupportedTypes( types=", ".join(address.ALLOWED_NETWORK_TYPES)) @@ -1059,7 +1119,8 @@ def _check_address_mode(op, interface, ihost, existing_interface): types=", ".join(address.ALLOWED_NETWORK_TYPES)) # Check for infrastructure specific requirements - if network_type == constants.NETWORK_TYPE_INFRA: + if any(network_type == constants.NETWORK_TYPE_INFRA + for network_type in networktypelist): if ipv4_mode != constants.IPV4_STATIC: if ipv6_mode != constants.IPV6_STATIC: raise exception.AddressModeMustBeStaticOnInfra() @@ -1118,22 +1179,48 @@ def _check_address_mode(op, interface, ihost, existing_interface): family=constants.IP_FAMILIES[constants.IPV6_FAMILY]) +def _check_networks(interface): + NONASSIGNABLE_WITH_OAM = [constants.NETWORK_TYPE_MGMT, + constants.NETWORK_TYPE_PXEBOOT, + constants.NETWORK_TYPE_INFRA] + ifclass = interface['ifclass'] + networks = interface['networks'] + if ifclass == constants.INTERFACE_CLASS_PLATFORM and len(networks) > 1: + networktypelist = [] + for network_id in networks: + network = pecan.request.dbapi.network_get_by_id(network_id) + networktypelist.append(network.type) + if constants.NETWORK_TYPE_PXEBOOT in networktypelist: + msg = _("An interface assigned with a network of " + "type '%s' cannot contain additional networks." + % constants.NETWORK_TYPE_PXEBOOT) + raise wsme.exc.ClientSideError(msg) + elif any(network_type in NONASSIGNABLE_WITH_OAM + for network_type in networktypelist) and \ + any(network_type == constants.NETWORK_TYPE_OAM + for network_type in networktypelist): + msg = _("An interface assigned with a network of " + "type '%s' cannot assign any networks " + "of type '%s'." + % (constants.NETWORK_TYPE_OAM, NONASSIGNABLE_WITH_OAM)) + raise wsme.exc.ClientSideError(msg) + + def _check_interface_data(op, interface, ihost, existing_interface): # Get data - ihost_id = interface['forihostid'] ihost_uuid = interface['ihost_uuid'] providernetworks = interface['providernetworks'] + ifclass = interface['ifclass'] networktypelist = [] - if interface['networktype']: - networktypelist = [network.strip() for network in interface['networktype'].split(",")] - - existing_networktypelist = [] - if existing_interface: - if existing_interface['networktype']: - existing_networktypelist = [network.strip() for network in existing_interface['networktype'].split(",")] - - network_type = cutils.get_primary_network_type(interface) + if ifclass == constants.INTERFACE_CLASS_PLATFORM: + for network_id in interface['networks']: + platform_network = pecan.request.dbapi.network_get_by_id(network_id) + networktypelist.append(platform_network.type) + elif ifclass: + networktypelist.append(ifclass) + else: + networktypelist.append(constants.INTERFACE_CLASS_NONE) # Get providernet dict all_providernetworks = _neutron_providernet_list() @@ -1163,24 +1250,21 @@ def _check_interface_data(op, interface, ihost, existing_interface): msg = _("VLAN id %s already in use on interface %s" % (str(vlan_id), lower_iface['ifname'])) raise wsme.exc.ClientSideError(msg) - if lower_iface['networktype']: - nt1 = [network.strip() for network in - interface['networktype'].split(",")] - nt2 = [network.strip() for network in - lower_iface['networktype'].split(",")] - ntset = set(nt1).union(nt2) - if any(set(c).issubset(ntset) for c in - INCOMPATIBLE_NETWORK_TYPES): - msg = _("%s VLAN cannot be created over an interface with " - "network type %s" % - (interface['networktype'], - lower_iface['networktype'])) - raise wsme.exc.ClientSideError(msg) + if (lower_iface['ifclass'] == constants.INTERFACE_CLASS_DATA and + interface['ifclass'] == constants.INTERFACE_CLASS_PLATFORM): + msg = _("Platform VLAN interface cannot be created over a data " + "interface ") + raise wsme.exc.ClientSideError(msg) + elif (lower_iface['ifclass'] == constants.INTERFACE_CLASS_PLATFORM and + interface['ifclass'] == constants.INTERFACE_CLASS_DATA): + msg = _("Data VLAN interface cannot be created over a platform " + "interface ") + raise wsme.exc.ClientSideError(msg) # Check if the 'uses' interface is already used by another AE or VLAN # interface interface_list = pecan.request.dbapi.iinterface_get_all( - forihostid=ihost_id) + forihostid=ihost_id) for i in interface_list: if i.id == this_interface_id: continue @@ -1195,17 +1279,24 @@ def _check_interface_data(op, interface, ihost, existing_interface): " AE interface {}".format(p, i.ifname)) raise wsme.exc.ClientSideError(msg) elif (i.iftype == constants.INTERFACE_TYPE_VLAN and - iftype != constants.INTERFACE_TYPE_VLAN): + iftype != constants.INTERFACE_TYPE_VLAN): msg = _("Interface {} is already used by another" " VLAN interface {}".format(p, i.ifname)) raise wsme.exc.ClientSideError(msg) + # check interface class validity + _check_interface_class(interface, existing_interface) + # check networktype combinations and transitions for validity _check_network_type(op, interface, ihost, existing_interface) # check mode/pool combinations and transitions for validity _check_address_mode(op, interface, ihost, existing_interface) + # check to ensure that the interface assigned with an OAM or + # PXEBOOT network has no other networks + _check_networks(interface) + # Make sure txhashpolicy for data is layer2 aemode = interface['aemode'] txhashpolicy = interface['txhashpolicy'] @@ -1262,7 +1353,6 @@ def _check_interface_data(op, interface, ihost, existing_interface): # can only be in ae mode 'active_standby' or 'balanced' if (any(network in [constants.NETWORK_TYPE_OAM, constants.NETWORK_TYPE_INFRA] for network in networktypelist) and iftype == 'ae' and (aemode not in VALID_AEMODE_LIST)): - msg = _("Device interface with network type '%s', and interface " "type 'aggregated ethernet' must be in mode 'active_standby' " "or 'balanced' or '802.3ad'." % (str(networktypelist))) @@ -1291,8 +1381,7 @@ def _check_interface_data(op, interface, ihost, existing_interface): # and none for 'oam', 'mgmt' and 'infra' # Ensure uniqueness wrt the providernetworks if (_neutron_providernet_extension_supported() and - any(nt in NEUTRON_NETWORK_TYPES for nt in networktypelist)): - + interface['ifclass'] in NEUTRON_INTERFACE_CLASS): if not providernetworks: msg = _("At least one provider network must be selected.") raise wsme.exc.ClientSideError(msg) @@ -1322,10 +1411,10 @@ def _check_interface_data(op, interface, ihost, existing_interface): # type. Ensure that the only provider type that # can be assigned is VLAN. if (providernet['type'] != constants.NEUTRON_PROVIDERNET_VLAN and - network_type not in NEUTRON_NETWORK_TYPES): + ifclass not in NEUTRON_NETWORK_TYPES): msg = _("Provider network '%s' of type '%s' cannot be assigned " - "to an interface with network type '%s'" - % (pn, providernet['type'], network_type)) + "to an interface with interface class '%s'" + % (pn, providernet['type'], ifclass)) raise wsme.exc.ClientSideError(msg) # This ensures that a specific provider network type can @@ -1357,7 +1446,7 @@ def _check_interface_data(op, interface, ihost, existing_interface): _update_shared_interface_neutron_bindings(ihost, interface, test=True) elif (not _neutron_providernet_extension_supported() and - any(nt in PCI_NETWORK_TYPES for nt in networktypelist)): + any(nt in PCI_NETWORK_TYPES for nt in networktypelist)): # When the neutron implementation is not our own and it does not # support our provider network extension we still want to do minimal # validation of the provider network list but we cannot do more @@ -1372,26 +1461,15 @@ def _check_interface_data(op, interface, ihost, existing_interface): format(', '.join(networktypelist))) raise wsme.exc.ClientSideError(msg) - elif (constants.NETWORK_TYPE_NONE not in networktypelist and constants.NETWORK_TYPE_DATA not in networktypelist and - constants.NETWORK_TYPE_DATA not in existing_networktypelist): + elif (interface['ifclass'] is not constants.INTERFACE_CLASS_NONE and + interface['ifclass'] != constants.INTERFACE_CLASS_DATA): if providernetworks is not None: msg = _("Provider network(s) not supported " - "for non-data interfaces. (%s) (%s)" % (str(networktypelist), str(existing_interface))) + "for non-data interfaces. (%s) (%s)" % (interface['ifclass'], str(existing_interface))) raise wsme.exc.ClientSideError(msg) else: interface['providernetworks'] = None - # Update MTU based on values to sent via DHCP - interface['ihost_uuid'] = ihost['uuid'] - if any(network in [constants.NETWORK_TYPE_MGMT, constants.NETWORK_TYPE_INFRA] for network in networktypelist): - try: - interface_network = pecan.request.dbapi.network_get_by_type( - network_type) - interface['imtu'] = interface_network.mtu - except exception.NetworkTypeNotFound: - msg = _("The %s network is not configured." % network_type) - raise wsme.exc.ClientSideError(msg) - # check MTU if interface['iftype'] == constants.INTERFACE_TYPE_VLAN: vlan_mtu = interface['imtu'] @@ -1420,8 +1498,14 @@ def _check_interface_data(op, interface, ihost, existing_interface): # find any interface in controller host that is of type infra interfaces = pecan.request.dbapi.iinterface_get_by_ihost(ihost=h['uuid']) for host_interface in interfaces: - if host_interface['networktype']: - hi_networktypelist = [network.strip() for network in host_interface['networktype'].split(",")] + if host_interface['ifclass']: + hi_networktypelist = [] + if host_interface['ifclass'] == constants.INTERFACE_CLASS_PLATFORM: + for network_id in host_interface['networks']: + network = pecan.request.dbapi.network_get_by_id(network_id) + hi_networktypelist.append(network.type) + else: + hi_networktypelist.append(host_interface['ifclass']) if constants.NETWORK_TYPE_INFRA in hi_networktypelist: infra_on_controller = True break @@ -1461,7 +1545,7 @@ def _check_ports(op, interface, ihost, ports): if p.interface_id and p.interface_id != this_interface_id: pif = pecan.request.dbapi.iinterface_get(p.interface_id) msg = _("Another interface %s is already using this port" - % pif.uuid) + % pif.uuid) raise wsme.exc.ClientSideError(msg) # If someone enters name with spaces anywhere, such as " eth2", "eth2 " @@ -1485,7 +1569,6 @@ def _check_ports(op, interface, ihost, ports): port_exists = False for pTwo in host_ports: if p == pTwo.name or p == pTwo.uuid: - # port exists port_exists = True break @@ -1543,19 +1626,22 @@ def _update_address_mode(interface, family, mode, pool): pecan.request.dbapi.address_mode_update(interface_id, updates) -def _delete_addressing(interface, family, orig_networktype): +def _delete_addressing(interface, family, existing_interface): interface_id = interface['id'] pecan.request.dbapi.routes_destroy_by_interface( interface_id, family) - if ((orig_networktype == constants.NETWORK_TYPE_OAM) or - (orig_networktype == constants.NETWORK_TYPE_PXEBOOT)): - pecan.request.dbapi.addresses_remove_interface_by_interface( - interface['id'] - ) - elif ((orig_networktype != constants.NETWORK_TYPE_MGMT) and - (orig_networktype != constants.NETWORK_TYPE_INFRA)): - pecan.request.dbapi.addresses_destroy_by_interface( - interface_id, family) + for network_id in existing_interface['networks']: + network = pecan.request.dbapi.network_get_by_id(network_id) + orig_networktype = network.type + if ((orig_networktype == constants.NETWORK_TYPE_OAM) or + (orig_networktype == constants.NETWORK_TYPE_PXEBOOT)): + pecan.request.dbapi.addresses_remove_interface_by_interface( + interface['id'] + ) + elif ((orig_networktype != constants.NETWORK_TYPE_MGMT) and + (orig_networktype != constants.NETWORK_TYPE_INFRA)): + pecan.request.dbapi.addresses_destroy_by_interface( + interface_id, family) pecan.request.dbapi.address_modes_destroy_by_interface( interface_id, family) @@ -1607,7 +1693,7 @@ def _add_extended_attributes(ihost, interface, attributes): that got added before sending the object to the database. """ interface_data = interface.as_dict() - networktype = cutils.get_primary_network_type(interface_data) + networktype = interface_data['networktype'] if networktype not in address.ALLOWED_NETWORK_TYPES: # No need to create new address mode records if the interface type # does not support it @@ -1642,7 +1728,7 @@ def _update_ports(op, interface, ihost, ports): values = {'interface_id': interface['id']} # else if old port disassociated elif ((p.uuid not in port_list and p.name not in port_list) and - p.interface_id and p.interface_id == this_interface_id): + p.interface_id and p.interface_id == this_interface_id): values = {'interface_id': None} # else move on else: @@ -1795,22 +1881,22 @@ def _get_shared_data_interfaces(ihost, interface): for ifname in uses: parent = pecan.request.dbapi.iinterface_get(ifname, ihost['uuid']) used_by.extend(parent['used_by']) - network_type = parent.get('networktype', None) - if network_type: - # This should only match 'data' networktype since that + interface_class = parent.get('ifclass', None) + if interface_class: + # This should only match 'data' interface class since that # is the only type that can be shared on multiple interfaces. - if any(network in [constants.NETWORK_TYPE_DATA] for network in network_type.split(",")): + if interface_class == constants.INTERFACE_CLASS_DATA: shared_data_interfaces.append(parent) else: used_by = interface['used_by'] for ifname in used_by: child = pecan.request.dbapi.iinterface_get(ifname, ihost['uuid']) - network_type = child.get('networktype', None) - if network_type: - # This should only match 'data' networktype since that + interface_class = child.get('ifclass', None) + if interface_class: + # This should only match 'data' interface class since that # is the only type that can be shared on multiple interfaces. - if any(network in [constants.NETWORK_TYPE_DATA] for network in network_type.split(",")): + if interface_class == constants.INTERFACE_CLASS_DATA: shared_data_interfaces.append(child) return shared_data_interfaces @@ -1886,17 +1972,15 @@ def _neutron_bind_interface(ihost, interface, test=False): if not _neutron_host_extension_supported(): # No action required if neutron does not support the host extension return - networktypelist = [] - if interface['networktype']: - networktypelist = [network.strip() for network in interface['networktype'].split(",")] - if constants.NETWORK_TYPE_DATA in networktypelist: + + if interface['ifclass'] == constants.INTERFACE_CLASS_DATA: networktype = constants.NETWORK_TYPE_DATA - elif constants.NETWORK_TYPE_PCI_PASSTHROUGH in networktypelist: + elif interface['ifclass'] == constants.INTERFACE_CLASS_PCI_PASSTHROUGH: networktype = constants.NETWORK_TYPE_PCI_PASSTHROUGH - elif constants.NETWORK_TYPE_PCI_SRIOV in networktypelist: + elif interface['ifclass'] == constants.INTERFACE_CLASS_PCI_SRIOV: networktype = constants.NETWORK_TYPE_PCI_SRIOV else: - msg = _("Invalid network type %s: " % interface['networktype']) + msg = _("Invalid interface class %s: " % interface['ifclass']) raise wsme.exc.ClientSideError(msg) interface_uuid = interface['uuid'] @@ -2034,6 +2118,9 @@ def _create(interface, from_profile=False): if not interface.get('uuid'): interface['uuid'] = str(uuid.uuid4()) + if 'ifclass' in interface and interface['ifclass'] == 'none': + interface.update({'ifclass': None}) + # Get ports ports = None uses_if = None @@ -2052,6 +2139,11 @@ def _create(interface, from_profile=False): elif 'used_by' not in interface: interface.update({'used_by': []}) + if 'networks' in interface and interface['networks'] is None: + interface.update({'networks': []}) + elif 'networks' not in interface: + interface.update({'networks': []}) + # Check mtu before setting defaults interface = _check_interface_mtu(interface, ihost, from_profile=from_profile) @@ -2070,8 +2162,24 @@ def _create(interface, from_profile=False): interface = set_interface_mac(ihost, interface) new_interface = pecan.request.dbapi.iinterface_create( - forihostid, - interface) + forihostid, + interface) + + # Create network-interface + try: + if (new_interface['ifclass'] and + new_interface['ifclass'] == constants.INTERFACE_CLASS_PLATFORM): + if 'networks' in interface.keys() and interface['networks']: + for network_id in interface['networks']: + values = {'interface_id': new_interface['id'], + 'network_id': network_id} + pecan.request.dbapi.interface_network_create(values) + except Exception as e: + LOG.exception("Failed to create network interface association: " + "new_interface={} interface={}".format( + new_interface.as_dict(), interface)) + pecan.request.dbapi.iinterface_destroy(new_interface.as_dict()['uuid']) + raise e try: # Add extended attributes stored in other tables @@ -2084,9 +2192,8 @@ def _create(interface, from_profile=False): raise e try: - if (interface['networktype'] and - (any(network.strip() in NEUTRON_NETWORK_TYPES for network in - interface['networktype'].split(",")))): + if (interface['ifclass'] and + interface['ifclass'] in NEUTRON_INTERFACE_CLASS): _neutron_bind_interface(ihost, new_interface.as_dict()) except Exception as e: LOG.exception("Failed to update neutron bindings: " @@ -2114,9 +2221,8 @@ def _create(interface, from_profile=False): LOG.exception("Failed to update ports for interface " "interfaces: new_interface={} ports={}".format( new_interface.as_dict(), ports)) - if (interface['networktype'] and - any(network.strip() in NEUTRON_NETWORK_TYPES for network in - interface['networktype'].split(","))): + if (interface['ifclass'] and + interface['ifclass'] in NEUTRON_INTERFACE_CLASS): _neutron_unbind_interface(ihost, new_interface.as_dict()) pecan.request.dbapi.iinterface_destroy(new_interface.as_dict()['uuid']) raise e @@ -2136,16 +2242,19 @@ def _create(interface, from_profile=False): if ihost['recordtype'] != "profile": try: - networktype = cutils.get_primary_network_type(new_interface) - if networktype == constants.NETWORK_TYPE_MGMT: - _update_host_mgmt_address(ihost, new_interface.as_dict()) - elif networktype == constants.NETWORK_TYPE_INFRA: - _update_host_infra_address(ihost, new_interface.as_dict()) - if ihost['personality'] == constants.CONTROLLER: - if networktype == constants.NETWORK_TYPE_OAM: - _update_host_oam_address(ihost, new_interface.as_dict()) - elif networktype == constants.NETWORK_TYPE_PXEBOOT: - _update_host_pxeboot_address(ihost, new_interface.as_dict()) + ifclass = new_interface['ifclass'] + if ifclass == constants.INTERFACE_CLASS_PLATFORM and interface['networks']: + for network_id in interface['networks']: + network = pecan.request.dbapi.network_get_by_id(network_id) + if network.type == constants.NETWORK_TYPE_MGMT: + _update_host_mgmt_address(ihost, new_interface.as_dict()) + elif network.type == constants.NETWORK_TYPE_INFRA: + _update_host_infra_address(ihost, new_interface.as_dict()) + if ihost['personality'] == constants.CONTROLLER: + if network.type == constants.NETWORK_TYPE_OAM: + _update_host_oam_address(ihost, new_interface.as_dict()) + elif network.type == constants.NETWORK_TYPE_PXEBOOT: + _update_host_pxeboot_address(ihost, new_interface.as_dict()) except Exception as e: LOG.exception( "Failed to add static infrastructure interface address: " @@ -2155,16 +2264,19 @@ def _create(interface, from_profile=False): raise e # Covers off LAG case here. - networktype = cutils.get_primary_network_type(new_interface) - if networktype == constants.NETWORK_TYPE_MGMT: - cutils.perform_distributed_cloud_config(pecan.request.dbapi, - new_interface['id']) + ifclass = new_interface['ifclass'] + if ifclass == constants.INTERFACE_CLASS_PLATFORM and new_interface['networks']: + for network_id in new_interface['networks']: + network = pecan.request.dbapi.network_get_by_id(network_id) + if network.type == constants.NETWORK_TYPE_MGMT: + cutils.perform_distributed_cloud_config(pecan.request.dbapi, + new_interface['id']) return new_interface def _check(op, interface, ports=None, ifaces=None, from_profile=False, - existing_interface=None): + existing_interface=None): # Semantic checks ihost = pecan.request.dbapi.ihost_get(interface['ihost_uuid']).as_dict() _check_host(ihost) @@ -2174,7 +2286,7 @@ def _check(op, interface, ports=None, ifaces=None, from_profile=False, if ifaces: interfaces = pecan.request.dbapi.iinterface_get_by_ihost(interface['ihost_uuid']) if len(ifaces) > 1 and \ - interface['iftype'] == constants.INTERFACE_TYPE_VLAN: + interface['iftype'] == constants.INTERFACE_TYPE_VLAN: # Can only have one interface associated to vlan interface type raise wsme.exc.ClientSideError( _("Can only have one interface for vlan type. (%s)" % ifaces)) @@ -2204,7 +2316,6 @@ def _check(op, interface, ports=None, ifaces=None, from_profile=False, def _update(interface_uuid, interface_values, from_profile): - return objects.interface.get_by_uuid(pecan.request.context, interface_uuid) @@ -2263,10 +2374,13 @@ def _delete(interface, from_profile=False): msg = _("Cannot delete an ethernet interface type.") raise wsme.exc.ClientSideError(msg) - if interface['iftype'] == constants.INTERFACE_TYPE_VIRTUAL and \ - interface['networktype'] == constants.NETWORK_TYPE_MGMT: - msg = _("Cannot delete a virtual management interface.") - raise wsme.exc.ClientSideError(msg) + if interface['networks']: + for network_id in interface['networks']: + network = pecan.request.dbapi.network_get_by_id(network_id) + if interface['iftype'] == constants.INTERFACE_TYPE_VIRTUAL and \ + network.type == constants.NETWORK_TYPE_MGMT: + msg = _("Cannot delete a virtual management interface.") + raise wsme.exc.ClientSideError(msg) # Update ports ports = pecan.request.dbapi.ethernet_port_get_all( @@ -2303,18 +2417,20 @@ def _delete(interface, from_profile=False): # Delete interface try: - primary_networktype = cutils.get_primary_network_type(interface) - if ((primary_networktype == constants.NETWORK_TYPE_MGMT) or - (primary_networktype == constants.NETWORK_TYPE_INFRA) or - (primary_networktype == constants.NETWORK_TYPE_PXEBOOT) or - (primary_networktype == constants.NETWORK_TYPE_OAM)): - pecan.request.dbapi.addresses_remove_interface_by_interface( - interface['id'] - ) + primary_ifclass = interface['ifclass'] + if primary_ifclass == constants.INTERFACE_CLASS_PLATFORM: + for network_id in interface['networks']: + network = pecan.request.dbapi.network_get_by_id(network_id) + if ((network.type == constants.NETWORK_TYPE_MGMT) or + (network.type == constants.NETWORK_TYPE_INFRA) or + (network.type == constants.NETWORK_TYPE_PXEBOOT) or + (network.type == constants.NETWORK_TYPE_OAM)): + pecan.request.dbapi.addresses_remove_interface_by_interface( + interface['id'] + ) pecan.request.dbapi.iinterface_destroy(interface['uuid']) - if (interface['networktype'] and - any(network.strip() in NEUTRON_NETWORK_TYPES for network in - interface['networktype'].split(","))): + if (interface['ifclass'] and + interface['ifclass'] in NEUTRON_INTERFACE_CLASS): # Unbind the interface in neutron _neutron_unbind_interface(ihost, interface) # Update shared data interface bindings, if required diff --git a/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/network_infra.py b/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/network_infra.py index bc5470f11d..1d6b5fe71a 100644 --- a/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/network_infra.py +++ b/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/network_infra.py @@ -215,10 +215,11 @@ class InfraNetworkController(rest.RestController): if utils.is_host_active_controller(host): interface_list = pecan.request.dbapi.iinterface_get_by_ihost( host.uuid) + network = pecan.request.dbapi.network_get_by_type(constants.NETWORK_TYPE_INFRA) for interface in interface_list: - if (cutils.get_primary_network_type(interface) == - constants.NETWORK_TYPE_INFRA): - return True + if interface['ifclass'] == constants.INTERFACE_CLASS_PLATFORM: + if str(network['id']) in interface['networks']: + return True raise wsme.exc.ClientSideError(_( "Infrastructure interface must be configured on the active " "controller prior to applying infrastructure network " @@ -376,10 +377,6 @@ class InfraNetworkController(rest.RestController): for index, field in enumerate(InfraNetwork.address_names.keys()): infra[field] = str(start_address + index) - self._check_mtu_syntax(infra) - self._check_vlan_id_syntax(infra) - self._check_interface_mtu(infra) - self._check_interface_vlan_id(infra) return infra def _create_infra_network(self, infra): @@ -407,17 +404,10 @@ class InfraNetworkController(rest.RestController): values = { 'type': constants.NETWORK_TYPE_INFRA, - 'mtu': infra['infra_mtu'], 'dynamic': mgmt_network.dynamic, 'address_pool_id': pool.id, - 'link_capacity': constants.LINK_SPEED_10G, } - if infra['infra_vlan_id']: - values.update({ - 'vlan_id': infra['infra_vlan_id'], - }) - pecan.request.dbapi.network_create(values) # reserve static network addresses @@ -565,10 +555,6 @@ class InfraNetworkController(rest.RestController): changed_fields.append(field) rpc_infra.save() - # If mtu or vlan has changed, update the infrastructure interface - if any(field in ['infra_mtu', 'infra_vlan_id'] - for field in changed_fields): - self._update_interface(infra) if action == constants.APPLY_ACTION: # perform rpc to conductor to perform config apply diff --git a/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/profile.py b/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/profile.py index af735bddcf..e2048a9fb7 100644 --- a/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/profile.py +++ b/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/profile.py @@ -72,7 +72,8 @@ CONF.import_opt('journal_default_size', group='journal') # Defines the fields that must be copied in/out of interface profiles -INTERFACE_PROFILE_FIELDS = ['ifname', 'iftype', 'imtu', 'networktype', 'aemode', +INTERFACE_PROFILE_FIELDS = ['ifname', 'iftype', 'imtu', 'networktype', + 'ifclass', 'aemode', 'txhashpolicy', 'forihostid', 'providernetworks', 'vlan_id', 'ipv4_mode', 'ipv6_mode', 'ipv4_pool', 'ipv6_pool', diff --git a/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/route.py b/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/route.py index 15ad240cbd..4424df2b42 100644 --- a/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/route.py +++ b/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/route.py @@ -46,8 +46,6 @@ SYSINV_ROUTE_MAX_PATHS = 4 # Defines the list of interface network types that support routes ALLOWED_NETWORK_TYPES = [constants.NETWORK_TYPE_DATA, - constants.NETWORK_TYPE_DATA_VRS, - constants.NETWORK_TYPE_CONTROL, constants.NETWORK_TYPE_MGMT] @@ -265,7 +263,7 @@ class RouteController(rest.RestController): def _check_interface_type(self, interface_id): interface = pecan.request.dbapi.iinterface_get(interface_id) - networktype = cutils.get_primary_network_type(interface) + networktype = interface['networktype'] if networktype not in ALLOWED_NETWORK_TYPES: raise exception.RoutesNotSupportedOnInterfaces(iftype=networktype) return @@ -334,13 +332,6 @@ class RouteController(rest.RestController): self._check_duplicate_route(host_id, route) self._check_duplicate_subnet(host_id, route) - def _check_allowed_routes(self, interface_id, route): - if route['prefix'] == 0: - interface = pecan.request.dbapi.iinterface_get(interface_id) - networktype = cutils.get_primary_network_type(interface) - if networktype in [constants.NETWORK_TYPE_DATA_VRS]: - raise exception.DefaultRouteNotAllowedOnVRSInterface() - def _create_route(self, route): route.validate_syntax() route = route.as_dict() @@ -350,7 +341,6 @@ class RouteController(rest.RestController): host_id, interface_id = self._get_parent_id(interface_uuid) # Check for semantic conflicts self._check_interface_type(interface_id) - self._check_allowed_routes(interface_id, route) self._check_route_conflicts(host_id, route) self._check_local_gateway(host_id, route) self._check_reachable_gateway(interface_id, route) diff --git a/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/system.py b/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/system.py index 353c31d497..fc65b5a7cb 100644 --- a/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/system.py +++ b/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/system.py @@ -586,6 +586,16 @@ class SystemController(rest.RestController): @wsme_pecan.wsexpose(int) def mgmtvlan(self): - mgmt_network = pecan.request.dbapi.network_get_by_type( - constants.NETWORK_TYPE_MGMT) - return mgmt_network.vlan_id if mgmt_network.vlan_id else 0 + local_hostname = cutils.get_local_controller_hostname() + controller = pecan.request.dbapi.ihost_get(local_hostname) + host_id = controller['id'] + interface_list = pecan.request.dbapi.iinterface_get_by_ihost(host_id) + for interface in interface_list: + for network_id in interface['networks']: + network = pecan.request.dbapi.network_get_by_id(network_id) + if network.type == constants.NETWORK_TYPE_MGMT: + if 'vlan_id' not in interface: + return 0 + else: + return interface['vlan_id'] + return None diff --git a/sysinv/sysinv/sysinv/sysinv/common/constants.py b/sysinv/sysinv/sysinv/sysinv/common/constants.py index 794dccefc4..d2fca746d7 100644 --- a/sysinv/sysinv/sysinv/sysinv/common/constants.py +++ b/sysinv/sysinv/sysinv/sysinv/common/constants.py @@ -584,14 +584,17 @@ NETWORK_TYPE_OAM = 'oam' NETWORK_TYPE_BM = 'bm' NETWORK_TYPE_MULTICAST = 'multicast' NETWORK_TYPE_DATA = 'data' -NETWORK_TYPE_DATA_VRS = 'data-vrs' -NETWORK_TYPE_CONTROL = 'control' NETWORK_TYPE_SYSTEM_CONTROLLER = 'system-controller' NETWORK_TYPE_PCI_PASSTHROUGH = 'pci-passthrough' NETWORK_TYPE_PCI_SRIOV = 'pci-sriov' NETWORK_TYPE_PXEBOOT = 'pxeboot' +PLATFORM_NETWORK_TYPES = [NETWORK_TYPE_PXEBOOT, + NETWORK_TYPE_MGMT, + NETWORK_TYPE_INFRA, + NETWORK_TYPE_OAM] + PCI_NETWORK_TYPES = [NETWORK_TYPE_PCI_PASSTHROUGH, NETWORK_TYPE_PCI_SRIOV] @@ -600,6 +603,12 @@ INTERFACE_TYPE_VLAN = 'vlan' INTERFACE_TYPE_AE = 'ae' INTERFACE_TYPE_VIRTUAL = 'virtual' +INTERFACE_CLASS_NONE = 'none' +INTERFACE_CLASS_PLATFORM = 'platform' +INTERFACE_CLASS_DATA = 'data' +INTERFACE_CLASS_PCI_PASSTHROUGH = 'pci-passthrough' +INTERFACE_CLASS_PCI_SRIOV = 'pci-sriov' + SM_MULTICAST_MGMT_IP_NAME = "sm-mgmt-ip" MTCE_MULTICAST_MGMT_IP_NAME = "mtce-mgmt-ip" PATCH_CONTROLLER_MULTICAST_MGMT_IP_NAME = "patch-controller-mgmt-ip" diff --git a/sysinv/sysinv/sysinv/sysinv/common/utils.py b/sysinv/sysinv/sysinv/sysinv/common/utils.py index bc148a9e21..b753dd7505 100644 --- a/sysinv/sysinv/sysinv/sysinv/common/utils.py +++ b/sysinv/sysinv/sysinv/sysinv/common/utils.py @@ -1058,19 +1058,22 @@ def get_primary_network_type(interface): network types, discards the secondary type (if any) and returns the primary network type. """ - if not interface['networktype'] or interface['networktype'] == constants.NETWORK_TYPE_NONE: + if not interface['ifclass'] or interface['ifclass'] == constants.INTERFACE_CLASS_NONE: return None - networktypes = get_network_type_list(interface) - if len(networktypes) > 1: - networktypes = [n for n in networktypes if n != constants.NETWORK_TYPE_DATA] - # If the network type is the combined PCI passthrough and SRIOV then - # return pci-sriov as the primary network type - if is_pci_network_types(networktypes): - return constants.NETWORK_TYPE_PCI_SRIOV - if len(networktypes) > 1: - raise exception.CannotDeterminePrimaryNetworkType( - iface=interface['uuid'], types=interface['networktype']) - return networktypes[0] + primary_network_type = None + if interface['ifclass'] == constants.INTERFACE_CLASS_DATA: + primary_network_type = constants.NETWORK_TYPE_DATA + elif interface['ifclass'] == constants.INTERFACE_CLASS_PCI_PASSTHROUGH: + primary_network_type = constants.NETWORK_TYPE_PCI_PASSTHROUGH + elif interface['ifclass'] == constants.INTERFACE_CLASS_PCI_SRIOV: + primary_network_type = constants.NETWORK_TYPE_PCI_SRIOV + elif interface['ifclass'] == constants.INTERFACE_CLASS_PLATFORM: + if not interface['networktype'] or interface[ + 'networktype'] == constants.NETWORK_TYPE_NONE: + return None + primary_network_type = interface['networktype'] + + return primary_network_type def get_sw_version(): @@ -1160,6 +1163,15 @@ def gethostbyname(hostname): return socket.getaddrinfo(hostname, None)[0][4][0] +def get_local_controller_hostname(): + try: + local_hostname = socket.gethostname() + except Exception as e: + raise exception.SysinvException(_( + "Failed to get the local hostname: %s") % str(e)) + return local_hostname + + def get_mate_controller_hostname(hostname=None): if not hostname: try: diff --git a/sysinv/sysinv/sysinv/sysinv/conductor/manager.py b/sysinv/sysinv/sysinv/sysinv/conductor/manager.py index 9cb2894c81..58edb75992 100644 --- a/sysinv/sysinv/sysinv/sysinv/conductor/manager.py +++ b/sysinv/sysinv/sysinv/sysinv/conductor/manager.py @@ -1244,10 +1244,20 @@ class ConductorManager(service.PeriodicService): port_list = self.dbapi.port_get_all(host_id) ports = dict((p['interface_id'], p) for p in port_list) for interface in interface_list: - iface_network_type = cutils.get_primary_network_type(interface) - if iface_network_type == network_type: + if interface.networktype == network_type: return cutils.get_interface_os_ifname(interface, ifaces, ports) + def _find_local_mgmt_interface_vlan_id(self): + """Lookup the local interface name for a given network type.""" + host_id = self.get_my_host_id() + interface_list = self.dbapi.iinterface_get_all(host_id, expunge=True) + for interface in interface_list: + if interface.networktype == constants.NETWORK_TYPE_MGMT: + if 'vlan_id' not in interface: + return 0 + else: + return interface['vlan_id'] + def _remove_leases_by_mac_address(self, mac_address): """Remove any leases that were added without a CID that we were not able to delete. This is specifically looking for leases on the pxeboot @@ -1734,20 +1744,19 @@ class ConductorManager(service.PeriodicService): if i.networktype == constants.NETWORK_TYPE_MGMT: break - mgmt_network = self.dbapi.network_get_by_type( - constants.NETWORK_TYPE_MGMT) - cloning = False for inic in inic_dict_array: LOG.debug("Processing inic %s" % inic) interface_exists = False networktype = None + ifclass = None bootp = None create_tagged_interface = False new_interface = None set_address_interface = False mtu = constants.DEFAULT_MTU port = None + vlan_id = self._find_local_mgmt_interface_vlan_id() # ignore port if no MAC address present, this will # occur for data port after they are configured via DPDK driver if not inic['mac']: @@ -1762,16 +1771,16 @@ class ConductorManager(service.PeriodicService): if ihost['hostname'] != hostname: # auto create management/pxeboot network for all # nodes but the active controller - if mgmt_network.vlan_id: + if vlan_id: create_tagged_interface = True networktype = constants.NETWORK_TYPE_PXEBOOT ifname = 'pxeboot0' else: networktype = constants.NETWORK_TYPE_MGMT ifname = 'mgmt0' + ifclass = constants.INTERFACE_CLASS_PLATFORM set_address_interface = True bootp = 'True' - mtu = mgmt_network.mtu clone_mac_updated = False for interface in iinterfaces: @@ -1834,6 +1843,7 @@ class ConductorManager(service.PeriodicService): 'imac': inic['mac'], 'imtu': mtu, 'iftype': 'ethernet', + 'ifclass': ifclass, 'networktype': networktype } @@ -1849,6 +1859,21 @@ class ConductorManager(service.PeriodicService): {'interface_id': new_interface['id'], 'bootp': bootp }) + if networktype in [constants.NETWORK_TYPE_MGMT, + constants.NETWORK_TYPE_PXEBOOT]: + network = self.dbapi.network_get_by_type(networktype) + # create interface network association + ifnet_dict = { + 'interface_id': new_interface['id'], + 'network_id': network['id'] + } + try: + self.dbapi.interface_network_create(ifnet_dict) + except Exception: + LOG.exception( + "Failed to create interface %s " + "network %s association" % + (new_interface['id'], network['id'])) except Exception: LOG.exception("Failed to create new interface %s" % inic['mac']) @@ -1860,11 +1885,12 @@ class ConductorManager(service.PeriodicService): 'forihostid': ihost['id'], 'ifname': 'mgmt0', 'imac': inic['mac'], - 'imtu': mgmt_network.mtu, + 'imtu': constants.DEFAULT_MTU, 'iftype': 'vlan', + 'ifclass': constants.INTERFACE_CLASS_PLATFORM, 'networktype': constants.NETWORK_TYPE_MGMT, 'uses': [ifname], - 'vlan_id': mgmt_network.vlan_id, + 'vlan_id': vlan_id, } try: @@ -1873,6 +1899,21 @@ class ConductorManager(service.PeriodicService): new_interface = self.dbapi.iinterface_create( ihost['id'], interface_dict ) + network = self.dbapi.network_get_by_type( + constants.NETWORK_TYPE_MGMT + ) + # create interface network association + ifnet_dict = { + 'interface_id': new_interface['id'], + 'network_id': network['id'] + } + try: + self.dbapi.interface_network_create(ifnet_dict) + except Exception: + LOG.exception( + "Failed to create interface %s " + "network %s association" % + (new_interface['id'], network['id'])) except Exception: LOG.exception( "Failed to create new vlan interface %s" % @@ -7891,7 +7932,7 @@ class ConductorManager(service.PeriodicService): if nettype: iinterfaces[:] = [i for i in iinterfaces if - cutils.get_primary_network_type(i) == nettype] + i.networktype == nettype] return iinterfaces def mgmt_ip_set_by_ihost(self, diff --git a/sysinv/sysinv/sysinv/sysinv/conductor/openstack.py b/sysinv/sysinv/sysinv/sysinv/conductor/openstack.py index e56d5d3542..c80ba692f3 100644 --- a/sysinv/sysinv/sysinv/sysinv/conductor/openstack.py +++ b/sysinv/sysinv/sysinv/sysinv/conductor/openstack.py @@ -470,10 +470,7 @@ class OpenStackOperator(object): try: iinterfaces = self.try_interface_get_by_host(ihost_uuid) for interface in iinterfaces: - networktypelist = [] - if interface.networktype: - networktypelist = [network.strip() for network in interface['networktype'].split(",")] - if constants.NETWORK_TYPE_DATA in networktypelist: + if interface['ifclass'] == constants.INTERFACE_CLASS_DATA: providernets = interface.providernetworks for providernet in providernets.split(',') if providernets else []: ihost_aggset_provider.add(aggregate_name_prefix + @@ -591,11 +588,7 @@ class OpenStackOperator(object): try: iinterfaces = self.try_interface_get_by_host(ihost_uuid) for interface in iinterfaces: - networktypelist = [] - if interface.networktype: - networktypelist = [network.strip() for network in - interface['networktype'].split(",")] - if constants.NETWORK_TYPE_DATA in networktypelist: + if interface['ifclass'] == constants.INTERFACE_CLASS_DATA: providernets = interface.providernetworks for providernet in ( providernets.split(',') if providernets else []): diff --git a/sysinv/sysinv/sysinv/sysinv/db/sqlalchemy/migrate_repo/versions/078_interface_class.py b/sysinv/sysinv/sysinv/sysinv/db/sqlalchemy/migrate_repo/versions/078_interface_class.py new file mode 100644 index 0000000000..7e4e96ea4c --- /dev/null +++ b/sysinv/sysinv/sysinv/sysinv/db/sqlalchemy/migrate_repo/versions/078_interface_class.py @@ -0,0 +1,33 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# +# Copyright (c) 2018 Wind River Systems, Inc. +# +# The right to copy, distribute, modify, or otherwise make use +# of this software may be licensed only pursuant to the terms +# of an applicable Wind River license agreement. +# + +from sqlalchemy import Column, MetaData, Table +from sqlalchemy import String +from sysinv.openstack.common import log + +ENGINE = 'InnoDB' +CHARSET = 'utf8' +LOG = log.getLogger(__name__) + + +def upgrade(migrate_engine): + """Perform sysinv database upgrade for network interface + """ + + meta = MetaData() + meta.bind = migrate_engine + + interface = Table('interfaces', meta, autoload=True) + interface.create_column(Column('ifclass', String(255))) + + +def downgrade(migrate_engine): + # As per other openstack components, downgrade is + # unsupported in this release. + raise NotImplementedError('SysInv database downgrade is unsupported.') diff --git a/sysinv/sysinv/sysinv/sysinv/db/sqlalchemy/migrate_repo/versions/079_network_column_remove.py b/sysinv/sysinv/sysinv/sysinv/db/sqlalchemy/migrate_repo/versions/079_network_column_remove.py new file mode 100644 index 0000000000..a0d23d26af --- /dev/null +++ b/sysinv/sysinv/sysinv/sysinv/db/sqlalchemy/migrate_repo/versions/079_network_column_remove.py @@ -0,0 +1,30 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# +# Copyright (c) 2018 Wind River Systems, Inc. +# +# The right to copy, distribute, modify, or otherwise make use +# of this software may be licensed only pursuant to the terms +# of an applicable Wind River license agreement. +# + +from sqlalchemy import MetaData, Table + +ENGINE = 'InnoDB' +CHARSET = 'utf8' + + +def upgrade(migrate_engine): + meta = MetaData() + meta.bind = migrate_engine + + network = Table('networks', meta, autoload=True) + network.drop_column('mtu') + network.drop_column('link_capacity') + network.drop_column('vlan_id') + return True + + +def downgrade(migrate_engine): + # As per other openstack components, downgrade is + # unsupported in this release. + raise NotImplementedError('SysInv database downgrade is unsupported.') diff --git a/sysinv/sysinv/sysinv/sysinv/db/sqlalchemy/models.py b/sysinv/sysinv/sysinv/sysinv/db/sqlalchemy/models.py index dc347aeb90..a6a91ef593 100644 --- a/sysinv/sysinv/sysinv/sysinv/db/sqlalchemy/models.py +++ b/sysinv/sysinv/sysinv/sysinv/db/sqlalchemy/models.py @@ -331,7 +331,7 @@ class iinterface(Base): iftype = Column(String(255)) imac = Column(String(255), unique=True) imtu = Column(Integer) - networktype = Column(String(255)) # e.g. mgmt, data, ext, api + networktype = Column(String(255)) aemode = Column(String(255)) # e.g. balanced, active_standby aedict = Column(JSONEncodedDict) # e.g. 802.3ad parameters txhashpolicy = Column(String(255)) # e.g. L2, L2L3, L3L4 @@ -362,7 +362,8 @@ class Interfaces(Base): iftype = Column(String(255)) ifname = Column(String(255)) - networktype = Column(String(255)) # e.g. mgmt, data, ext, api + ifclass = Column(String(255)) + networktype = Column(String(255)) ifcapabilities = Column(JSONEncodedDict) farend = Column(JSONEncodedDict) sriov_numvfs = Column(Integer) @@ -1153,9 +1154,6 @@ class Networks(Base): name = Column(String(255), unique=True) type = Column(String(255), unique=True) dynamic = Column(Boolean, nullable=False) - link_capacity = Column(Integer) - mtu = Column(Integer, nullable=False) - vlan_id = Column(Integer) address_pool_id = Column(Integer, ForeignKey('address_pools.id', diff --git a/sysinv/sysinv/sysinv/sysinv/objects/interface.py b/sysinv/sysinv/sysinv/sysinv/objects/interface.py index 45d51ad296..26855361d1 100644 --- a/sysinv/sysinv/sysinv/sysinv/objects/interface.py +++ b/sysinv/sysinv/sysinv/sysinv/objects/interface.py @@ -79,6 +79,15 @@ def get_host_uuid(field, db_server): return host_uuid +def get_networks(field, db_object): + result = [] + if hasattr(db_object, 'interface_networks'): + for entry in getattr(db_object, 'interface_networks', []): + id_str = str(entry.network_id) + result.append(id_str) + return result + + class Interface(base.SysinvObject): # VERSION 1.0: Initial version # VERSION 1.1: Added VLAN and uses/used_by interface support @@ -94,6 +103,7 @@ class Interface(base.SysinvObject): 'ifname': utils.str_or_none, 'iftype': utils.str_or_none, + 'ifclass': utils.str_or_none, 'imac': utils.str_or_none, 'imtu': utils.int_or_none, 'networktype': utils.str_or_none, @@ -102,6 +112,7 @@ class Interface(base.SysinvObject): 'txhashpolicy': utils.str_or_none, 'providernetworks': utils.str_or_none, 'providernetworksdict': utils.dict_or_none, + 'networks': utils.list_of_strings_or_none, 'ifcapabilities': utils.dict_or_none, @@ -124,7 +135,8 @@ class Interface(base.SysinvObject): 'ipv6_mode': get_ipv6_address_mode, 'ipv4_pool': get_ipv4_address_pool, 'ipv6_pool': get_ipv6_address_pool, - 'ihost_uuid': get_host_uuid} + 'ihost_uuid': get_host_uuid, + 'networks': get_networks} _optional_fields = ['aemode', 'txhashpolicy', 'schedpolicy', 'vlan_id', 'vlan_type'] diff --git a/sysinv/sysinv/sysinv/sysinv/objects/network.py b/sysinv/sysinv/sysinv/sysinv/objects/network.py index d54f7a4530..d8308feebc 100644 --- a/sysinv/sysinv/sysinv/sysinv/objects/network.py +++ b/sysinv/sysinv/sysinv/sysinv/objects/network.py @@ -25,9 +25,6 @@ class Network(base.SysinvObject): 'type': utils.str_or_none, 'dynamic': utils.bool_or_none, 'pool_uuid': utils.uuid_or_none, - 'mtu': utils.int_or_none, - 'link_capacity': utils.int_or_none, - 'vlan_id': utils.int_or_none, } _foreign_fields = {'pool_uuid': 'address_pool:uuid'} diff --git a/sysinv/sysinv/sysinv/sysinv/objects/network_infra.py b/sysinv/sysinv/sysinv/sysinv/objects/network_infra.py index 7bc0381824..360d6df416 100644 --- a/sysinv/sysinv/sysinv/sysinv/objects/network_infra.py +++ b/sysinv/sysinv/sysinv/sysinv/objects/network_infra.py @@ -34,8 +34,6 @@ class InfraNetwork(base.SysinvObject): 'infra_subnet': utils.str_or_none, 'infra_start': utils.str_or_none, 'infra_end': utils.str_or_none, - 'infra_mtu': utils.str_or_none, - 'infra_vlan_id': utils.str_or_none, 'infra_c0_ip': utils.str_or_none, 'infra_c1_ip': utils.str_or_none, @@ -74,8 +72,6 @@ class InfraNetwork(base.SysinvObject): 'infra_subnet': subnet, 'infra_start': address_range.start, 'infra_end': address_range.end, - 'infra_mtu': network.mtu, - 'infra_vlan_id': network.vlan_id, }) # update standard DB fields (i.e. id, uuid) @@ -124,13 +120,6 @@ class InfraNetwork(base.SysinvObject): values = {'address': self[field]} self.dbapi.address_update(address.uuid, values) - # update infrastructure network entry - values = { - 'mtu': self['infra_mtu'], - 'vlan_id': self['infra_vlan_id'], - } - self.dbapi.network_update(self.uuid, values) - self.obj_reset_changes() @staticmethod diff --git a/sysinv/sysinv/sysinv/sysinv/puppet/interface.py b/sysinv/sysinv/sysinv/sysinv/puppet/interface.py index 44fdb6021e..9e5f78d098 100644 --- a/sysinv/sysinv/sysinv/sysinv/puppet/interface.py +++ b/sysinv/sysinv/sysinv/sysinv/puppet/interface.py @@ -7,7 +7,6 @@ import collections import copy import six -import uuid from netaddr import IPAddress from netaddr import IPNetwork @@ -26,16 +25,18 @@ LOG = log.getLogger(__name__) PLATFORM_NETWORK_TYPES = [constants.NETWORK_TYPE_PXEBOOT, constants.NETWORK_TYPE_MGMT, constants.NETWORK_TYPE_INFRA, - constants.NETWORK_TYPE_OAM, - constants.NETWORK_TYPE_DATA_VRS, # For HP/Nuage - constants.NETWORK_TYPE_BM, # For internal use only - constants.NETWORK_TYPE_CONTROL] + constants.NETWORK_TYPE_OAM] DATA_NETWORK_TYPES = [constants.NETWORK_TYPE_DATA] +DATA_INTERFACE_CLASSES = [constants.INTERFACE_CLASS_DATA] + PCI_NETWORK_TYPES = [constants.NETWORK_TYPE_PCI_SRIOV, constants.NETWORK_TYPE_PCI_PASSTHROUGH] +PCI_INTERFACE_CLASSES = [constants.INTERFACE_CLASS_PCI_PASSTHROUGH, + constants.INTERFACE_CLASS_PCI_SRIOV] + ACTIVE_STANDBY_AE_MODES = ['active_backup', 'active-backup', 'active_standby'] BALANCED_AE_MODES = ['balanced', 'balanced-xor'] LACP_AE_MODES = ['802.3ad'] @@ -77,14 +78,6 @@ class InterfacePuppet(base.BasePuppet): # use when parsing the interface list. context = self._create_interface_context(host) - if host.personality == constants.CONTROLLER: - # Insert a fake BMC interface because BMC information is only - # stored on the host and in the global config. This makes it - # easier to setup the BMC interface from the interface handling - # code. Hopefully we can add real interfaces in the DB some day - # and remove this code. - self._create_bmc_interface(host, context) - # interface configuration is organized into sets of network_config, # route_config and address_config resource hashes (dict) config = { @@ -137,62 +130,17 @@ class InterfacePuppet(base.BasePuppet): } return context - def _create_bmc_interface(self, host, context): - """ - Creates a fake BMC interface and inserts it into the context interface - list. It also creates a fake BMC address and inserts it into the - context address list. This is required because these two entities - exist only as attributes on the host and in local context variables. - Rather than have different code to generate manifest entries based on - these other data structures it is easier to create fake context entries - and re-use the existing code base. - """ - try: - network = self.dbapi.network_get_by_type( - constants.NETWORK_TYPE_BM) - except exception.NetworkTypeNotFound: - # No BMC network configured - return - - lower_iface = _find_bmc_lower_interface(context) - if not lower_iface: - # No mgmt or pxeboot? - return - - addr = self._get_address_by_name(host.hostname, - constants.NETWORK_TYPE_BM) - - iface = { - 'uuid': str(uuid.uuid4()), - 'ifname': 'bmc0', - 'iftype': constants.INTERFACE_TYPE_VLAN, - 'networktype': constants.NETWORK_TYPE_BM, - 'imtu': network.mtu, - 'vlan_id': network.vlan_id, - 'uses': [lower_iface['ifname']], - 'used_by': [] - } - - lower_iface['used_by'] = ['bmc0'] - address = { - 'ifname': iface['ifname'], - 'family': addr.family, - 'prefix': addr.prefix, - 'address': addr.address, - 'networktype': iface['networktype'] - } - - context['interfaces'].update({iface['ifname']: iface}) - context['addresses'].update({iface['ifname']: [address]}) - def _find_host_interface(self, host, networktype): """ Search the host interface list looking for an interface with a given primary network type. """ for iface in self.dbapi.iinterface_get_by_ihost(host.id): - if networktype == utils.get_primary_network_type(iface): - return iface + for ni in self.dbapi.interface_network_get_by_interface( + iface['id']): + network = self.dbapi.network_get(ni.id) + if network.type == networktype: + return iface def _get_port_interface_id_index(self, host): """ @@ -328,30 +276,11 @@ class InterfacePuppet(base.BasePuppet): def is_platform_network_type(iface): - networktype = utils.get_primary_network_type(iface) - return bool(networktype in PLATFORM_NETWORK_TYPES) + return bool(iface['ifclass'] == constants.INTERFACE_CLASS_PLATFORM) def is_data_network_type(iface): - networktypelist = utils.get_network_type_list(iface) - return bool(any(n in DATA_NETWORK_TYPES for n in networktypelist)) - - -def _find_bmc_lower_interface(context): - """ - Search the profile interface list looking for either a pxeboot or mgmt - interface that can be used to attach a BMC VLAN interface. If a pxeboot - interface exists then it is preferred since we do not want to create a VLAN - over another VLAN interface. - """ - selected_iface = None - for ifname, iface in six.iteritems(context['interfaces']): - networktype = utils.get_primary_network_type(iface) - if networktype == constants.NETWORK_TYPE_PXEBOOT: - return iface - elif networktype == constants.NETWORK_TYPE_MGMT: - selected_iface = iface - return selected_iface + return bool(iface['ifclass'] == constants.INTERFACE_CLASS_DATA) def is_controller(context): @@ -378,8 +307,7 @@ def is_pci_interface(iface): """ Determine if the interface is one of the PCI device types. """ - networktype = utils.get_primary_network_type(iface) - return bool(networktype in PCI_NETWORK_TYPES) + return bool(iface['ifclass'] in PCI_INTERFACE_CLASSES) def is_platform_interface(context, iface): @@ -594,14 +522,6 @@ def get_interface_routes(context, iface): return context['routes'][iface['ifname']] -def get_network_speed(context, networktype): - if 'networks' in context: - network = context['networks'].get(networktype, None) - if network: - return network['link_capacity'] - return 0 - - def _set_address_netmask(address): """ The netmask is not supplied by sysinv but is required by the puppet @@ -615,14 +535,20 @@ def _set_address_netmask(address): return address -def get_interface_primary_address(context, iface): +def get_interface_primary_address(context, iface, network_id=None): """ Determine the primary IP address on an interface (if any). If multiple addresses exist then the first address is returned. """ addresses = context['addresses'].get(iface['ifname'], []) - if len(addresses) > 0: + if len(addresses) > 0 and network_id is None: return _set_address_netmask(addresses[0]) + elif network_id: + for address in addresses: + net = find_network_by_pool_uuid(context, + address.pool_uuid) + if net and network_id == net.id: + return _set_address_netmask(address) def get_interface_address_family(context, iface): @@ -640,11 +566,10 @@ def get_interface_address_family(context, iface): return 'inet6' -def get_interface_gateway_address(context, iface): +def get_interface_gateway_address(context, networktype): """ Determine if the interface has a default gateway. """ - networktype = utils.get_primary_network_type(iface) return context['gateways'].get(networktype, None) @@ -652,32 +577,25 @@ def get_interface_address_method(context, iface): """ Determine what type of interface to configure for each network type. """ - networktype = utils.get_primary_network_type(iface) - if not networktype: + + if not iface.ifclass or iface.ifclass == constants.INTERFACE_CLASS_NONE: # Interfaces that are configured purely as a dependency from other # interfaces (i.e., vlan lower interface, bridge member, bond slave) # should be left as manual config return 'manual' - elif networktype in DATA_NETWORK_TYPES: + elif iface.ifclass == constants.INTERFACE_CLASS_DATA: # All data interfaces configured in the kernel because they are not # natively supported in vswitch or need to be shared with the kernel # because of a platform VLAN should be left as manual config return 'manual' - elif networktype == constants.NETWORK_TYPE_CONTROL: - return 'static' - elif networktype == constants.NETWORK_TYPE_DATA_VRS: - # All HP/Nuage interfaces have their own IP address defined statically - return 'static' - elif networktype == constants.NETWORK_TYPE_BM: - return 'static' - elif networktype in PCI_NETWORK_TYPES: + elif iface.ifclass in PCI_INTERFACE_CLASSES: return 'manual' else: if is_controller(context): # All other interface types that exist on a controller are setup # statically since the controller themselves run the DHCP server. return 'static' - elif networktype == constants.NETWORK_TYPE_PXEBOOT: + elif iface.networktype == constants.NETWORK_TYPE_PXEBOOT: # All pxeboot interfaces that exist on non-controller nodes are set # to manual as they are not needed/used once the install is done. # They exist only in support of the vlan mgmt interface above it. @@ -691,14 +609,16 @@ def get_interface_traffic_classifier(context, iface): """ Get the interface traffic classifier command line (if any) """ - networktype = utils.get_primary_network_type(iface) - if networktype in [constants.NETWORK_TYPE_MGMT, - constants.NETWORK_TYPE_INFRA]: - networkspeed = get_network_speed(context, networktype) - return '/usr/local/bin/cgcs_tc_setup.sh %s %s %s > /dev/null' % ( - get_interface_os_ifname(context, iface), - networktype, - networkspeed) + + for net_id in iface.networks: + networktype = find_networktype_by_network_id(context, int(net_id)) + if networktype in [constants.NETWORK_TYPE_MGMT, + constants.NETWORK_TYPE_INFRA]: + networkspeed = constants.LINK_SPEED_10G + return '/usr/local/bin/cgcs_tc_setup.sh %s %s %s > /dev/null' \ + % (get_interface_os_ifname(context, iface), + networktype, + networkspeed) return None @@ -879,7 +799,7 @@ def get_ethernet_network_config(context, iface, config): Augments a basic config dictionary with the attributes specific to an ethernet interface. """ - networktype = utils.get_primary_network_type(iface) + interface_class = iface['ifclass'] options = {} # Increased to accommodate devices that require more time to # complete link auto-negotiation @@ -890,7 +810,7 @@ def get_ethernet_network_config(context, iface, config): options['SLAVE'] = 'yes' options['MASTER'] = get_master_interface(context, iface) options['PROMISC'] = 'yes' - elif networktype == constants.NETWORK_TYPE_PCI_SRIOV: + elif interface_class == constants.INTERFACE_CLASS_PCI_SRIOV: if not is_a_mellanox_cx3_device(context, iface): # CX3 device can only use kernel module options to enable vfs # others share the same pci-sriov sysfs enabling mechanism @@ -898,7 +818,7 @@ def get_ethernet_network_config(context, iface, config): get_interface_port_name(context, iface)) options['pre_up'] = "echo 0 > %s; echo %s > %s" % ( sriovfs_path, iface['sriov_numvfs'], sriovfs_path) - elif networktype == constants.NETWORK_TYPE_PCI_PASSTHROUGH: + elif interface_class == constants.INTERFACE_CLASS_PCI_PASSTHROUGH: sriovfs_path = ("/sys/class/net/%s/device/sriov_numvfs" % get_interface_port_name(context, iface)) options['pre_up'] = "if [ -f %s ]; then echo 0 > %s; fi" % ( @@ -931,35 +851,38 @@ def get_route_config(route, ifname): return config -def get_common_network_config(context, iface, config): +def get_common_network_config(context, iface, config, network_id=None): """ Augments a basic config dictionary with the attributes specific to an upper layer interface (i.e., an interface that is used to terminate IP traffic). """ - traffic_classifier = get_interface_traffic_classifier(context, iface) - if traffic_classifier: - config['options']['post_up'] = traffic_classifier + LOG.debug("get_common_network_config %s %s network_id=%s" % + (iface.ifname, iface.networks, network_id)) + if network_id is None: + traffic_classifier = get_interface_traffic_classifier(context, iface) + if traffic_classifier: + config['options']['post_up'] = traffic_classifier method = get_interface_address_method(context, iface) if method == 'static': - address = get_interface_primary_address(context, iface) + address = get_interface_primary_address(context, iface, network_id) if address is None: - networktype = utils.get_primary_network_type(iface) - # control interfaces are not required to have an IP address - if networktype == constants.NETWORK_TYPE_CONTROL: - return config LOG.error("Interface %s has no primary address" % iface['ifname']) assert address is not None + config['ipaddress'] = address['address'] config['netmask'] = address['netmask'] - gateway = get_interface_gateway_address(context, iface) - if gateway: - config['gateway'] = gateway + if network_id is None and len(iface.networks) > 0: + networktype = find_networktype_by_network_id( + context, int(iface.networks[0])) + gateway = get_interface_gateway_address(context, networktype) + if gateway: + config['gateway'] = gateway return config -def get_interface_network_config(context, iface): +def get_interface_network_config(context, iface, network_id=None): """ Builds a network_config resource dictionary for a given interface """ @@ -972,7 +895,7 @@ def get_interface_network_config(context, iface): os_ifname, method=method, family=family, mtu=mtu) # Add options common to all top level interfaces - config = get_common_network_config(context, iface, config) + config = get_common_network_config(context, iface, config, network_id) # Add type specific options if iface['iftype'] == constants.INTERFACE_TYPE_VLAN: @@ -1018,11 +941,19 @@ def generate_network_config(context, config, iface): bridge, or to add additional route resources. """ network_config = get_interface_network_config(context, iface) - config[NETWORK_CONFIG_RESOURCE].update({ network_config['ifname']: format_network_config(network_config) }) + if len(iface.networks) > 1: + for net_id in iface.networks: + net_config = get_interface_network_config(context, iface, + int(net_id)) + ifname = net_config['ifname'] + ':' + net_id + config[NETWORK_CONFIG_RESOURCE].update({ + ifname: format_network_config(net_config) + }) + # Add additional configs for special interfaces if is_bridged_interface(context, iface): avp_config, bridge_config = get_bridged_network_config(context, iface) @@ -1039,6 +970,25 @@ def generate_network_config(context, config, iface): }) +def find_network_by_pool_uuid(context, pool_uuid): + for networktype, network in six.iteritems(context['networks']): + if network.pool_uuid == pool_uuid: + return network + return None + + +def find_network_id_by_networktype(context, networktype): + for net_type, network in six.iteritems(context['networks']): + if networktype == net_type: + return network.id + + +def find_networktype_by_network_id(context, network_id): + for networktype, network in six.iteritems(context['networks']): + if network.id == network_id: + return networktype + + def find_interface_by_type(context, networktype): """ Lookup an interface based on networktype. This is only intended for @@ -1046,8 +996,10 @@ def find_interface_by_type(context, networktype): mgmt, infra, pxeboot, bmc). """ for ifname, iface in six.iteritems(context['interfaces']): - if networktype == utils.get_primary_network_type(iface): - return iface + for net_id in iface.networks: + net_type = find_networktype_by_network_id(context, int(net_id)) + if networktype == net_type: + return iface def find_address_by_type(context, networktype): @@ -1074,23 +1026,12 @@ def find_sriov_interfaces_by_driver(context, driver): if iface['iftype'] != constants.INTERFACE_TYPE_ETHERNET: continue port = get_interface_port(context, iface) - networktype = utils.get_primary_network_type(iface) if (port['driver'] == driver and - networktype == constants.NETWORK_TYPE_PCI_SRIOV): + iface['ifclass'] == constants.INTERFACE_CLASS_PCI_SRIOV): ifaces.append(iface) return ifaces -def count_interfaces_by_type(context, networktypes): - """ - Count the number of interfaces with a matching network type. - """ - for ifname, iface in six.iteritems(context['interfaces']): - networktypelist = utils.get_network_type_list(iface) - if any(n in networktypelist for n in networktypes): - return iface - - def interface_sort_key(iface): """ Sort interfaces by interface type placing ethernet interfaces ahead of diff --git a/sysinv/sysinv/sysinv/sysinv/puppet/networking.py b/sysinv/sysinv/sysinv/sysinv/puppet/networking.py index a91be39fa8..d450ee69de 100644 --- a/sysinv/sysinv/sysinv/sysinv/puppet/networking.py +++ b/sysinv/sysinv/sysinv/sysinv/puppet/networking.py @@ -170,8 +170,6 @@ class NetworkingPuppet(base.BasePuppet): controller0_address, 'platform::network::%s::params::controller1_address' % networktype: controller1_address, - 'platform::network::%s::params::mtu' % networktype: - network.mtu, } def _get_pxeboot_interface_config(self): @@ -195,14 +193,15 @@ class NetworkingPuppet(base.BasePuppet): if network_interface: interface_name = interface.get_interface_os_ifname( self.context, network_interface) - + network_id = interface.find_network_id_by_networktype( + self.context, networktype) config.update({ 'platform::network::%s::params::interface_name' % networktype: interface_name }) interface_address = interface.get_interface_primary_address( - self.context, network_interface) + self.context, network_interface, network_id) if interface_address: config.update({ 'platform::network::%s::params::interface_address' % diff --git a/sysinv/sysinv/sysinv/sysinv/puppet/neutron.py b/sysinv/sysinv/sysinv/sysinv/puppet/neutron.py index 9b8ba72409..c0ad9175d9 100644 --- a/sysinv/sysinv/sysinv/sysinv/puppet/neutron.py +++ b/sysinv/sysinv/sysinv/sysinv/puppet/neutron.py @@ -162,8 +162,7 @@ class NeutronPuppet(openstack.OpenstackBasePuppet): device_mappings = [] for iface in self.context['interfaces'].values(): - if (utils.get_primary_network_type(iface) == - constants.NETWORK_TYPE_PCI_SRIOV): + if (iface['ifclass'] in [constants.INTERFACE_CLASS_PCI_SRIOV]): port = interface.get_interface_port(self.context, iface) providernets = interface.get_interface_providernets(iface) for net in providernets: diff --git a/sysinv/sysinv/sysinv/sysinv/puppet/nova.py b/sysinv/sysinv/sysinv/sysinv/puppet/nova.py index 146cc89ec3..bb88c00bfc 100644 --- a/sysinv/sysinv/sysinv/sysinv/puppet/nova.py +++ b/sysinv/sysinv/sysinv/sysinv/puppet/nova.py @@ -12,7 +12,6 @@ import subprocess from sysinv.common import constants from sysinv.common import exception -from sysinv.common import utils from . import openstack from . import interface @@ -585,10 +584,7 @@ class NovaPuppet(openstack.OpenstackBasePuppet): # the list of devices to whitelist devices = [] for iface in self.context['interfaces'].values(): - network_type = utils.get_primary_network_type(iface) - networktypes = utils.get_network_type_list(iface) - if (network_type == constants.NETWORK_TYPE_PCI_PASSTHROUGH or - utils.is_pci_network_types(networktypes)): + if iface['ifclass'] in [constants.INTERFACE_CLASS_PCI_PASSTHROUGH]: port = interface.get_interface_port(self.context, iface) device = { 'address': port['pciaddr'], @@ -617,8 +613,7 @@ class NovaPuppet(openstack.OpenstackBasePuppet): # the list of devices to whitelist devices = [] for iface in self.context['interfaces'].values(): - network_type = utils.get_primary_network_type(iface) - if network_type == constants.NETWORK_TYPE_PCI_SRIOV: + if iface['ifclass'] in [constants.INTERFACE_CLASS_PCI_SRIOV]: port = interface.get_interface_port(self.context, iface) device = { 'address': port['pciaddr'], diff --git a/sysinv/sysinv/sysinv/sysinv/puppet/platform.py b/sysinv/sysinv/sysinv/sysinv/puppet/platform.py index 9e24d11cb4..9de4828053 100644 --- a/sysinv/sysinv/sysinv/sysinv/puppet/platform.py +++ b/sysinv/sysinv/sysinv/sysinv/puppet/platform.py @@ -478,7 +478,6 @@ class PlatformPuppet(base.BasePuppet): drbdconfig = self.dbapi.drbdconfig_get_one() return { 'platform::drbd::params::link_util': str(drbdconfig.link_util), - 'platform::drbd::params::link_speed': self._get_drbd_link_speed(), 'platform::drbd::params::num_parallel': str(drbdconfig.num_parallel), 'platform::drbd::params::rtt_ms': str(drbdconfig.rtt_ms), } @@ -738,31 +737,24 @@ class PlatformPuppet(base.BasePuppet): return config - def _get_drbd_link_speed(self): - # return infra link speed if provisioned, otherwise mgmt - try: - infra_network = self.dbapi.network_get_by_type( - constants.NETWORK_TYPE_INFRA) - drbd_link_speed = infra_network.link_capacity - except exception.NetworkTypeNotFound: - mgmt_network = self.dbapi.network_get_by_type( - constants.NETWORK_TYPE_MGMT) - drbd_link_speed = mgmt_network.link_capacity - - return drbd_link_speed - def _get_nfs_config(self): # Calculate the optimal NFS r/w size based on the network mtu based # on the configured network(s) + mtu = constants.DEFAULT_MTU try: - infra_network = self.dbapi.network_get_by_type( + interfaces = self.dbapi.iinterface_get_by_network( constants.NETWORK_TYPE_INFRA) - mtu = infra_network.mtu - except exception.NetworkTypeNotFound: - mgmt_network = self.dbapi.network_get_by_type( - constants.NETWORK_TYPE_MGMT) - mtu = mgmt_network.mtu + for interface in interfaces: + mtu = interface.imtu + except exception.InvalidParameterValue: + try: + interfaces = self.dbapi.iinterface_get_by_network( + constants.NETWORK_TYPE_MGMT) + for interface in interfaces: + mtu = interface.imtu + except exception.InvalidParameterValue: + pass if self._get_address_by_name( constants.CONTROLLER_PLATFORM_NFS, diff --git a/sysinv/sysinv/sysinv/sysinv/tests/api/test_interface.py b/sysinv/sysinv/sysinv/sysinv/tests/api/test_interface.py index 305dd8f0cc..68289ccc6d 100644 --- a/sysinv/sysinv/sysinv/sysinv/tests/api/test_interface.py +++ b/sysinv/sysinv/sysinv/sysinv/tests/api/test_interface.py @@ -211,18 +211,21 @@ class InterfaceTestCase(base.FunctionalTest): prefix=23) self.mgmt_network = dbutils.create_test_network( id=1, + name='mgmt', type=constants.NETWORK_TYPE_MGMT, link_capacity=1000, vlan_id=2, address_pool_id=self.address_pool1.id) self.infra_network = dbutils.create_test_network( id=2, + name='infra', type=constants.NETWORK_TYPE_INFRA, link_capacity=10000, vlan_id=3, address_pool_id=self.address_pool2.id) self.oam_network = dbutils.create_test_network( id=3, + name='oam', type=constants.NETWORK_TYPE_OAM, address_pool_id=self.address_pool_oam.id) self.oam_address = dbutils.create_test_address( @@ -231,6 +234,10 @@ class InterfaceTestCase(base.FunctionalTest): prefix=24, name='controller-0-oam', address_pool_id=self.address_pool_oam.id) + self.pxeboot_network = dbutils.create_test_network( + id=4, + type=constants.NETWORK_TYPE_PXEBOOT, + address_pool_id=self.address_pool_pxeboot.id) self.pxeboot_address = dbutils.create_test_address( family=2, address='192.168.202.3', @@ -254,16 +261,28 @@ class InterfaceTestCase(base.FunctionalTest): self.compute = host return - def _create_ethernet(self, ifname=None, networktype=None, + def _create_ethernet(self, ifname=None, networktype=None, ifclass=None, providernetworks=None, host=None, expect_errors=False): - if isinstance(networktype, list): + if not isinstance(networktype, list): + networktypelist = [networktype] + else: + networktypelist = networktype networktype = ','.join(networktype) interface_id = len(self.profile['interfaces']) + 1 + networks = [] if not ifname: ifname = (networktype or 'eth') + str(interface_id) if not host: host = self.controller - + if all(network_type in constants.PLATFORM_NETWORK_TYPES + for network_type in networktypelist): + dbapi = db_api.get_instance() + ifclass = constants.INTERFACE_CLASS_PLATFORM + for network_type in networktypelist: + network = dbapi.network_get_by_type(network_type) + networks.append(str(network.id)) + if not ifclass and networktype: + ifclass = networktype port_id = len(self.profile['ports']) port = dbutils.create_test_ethernet_port( id=port_id, @@ -277,12 +296,15 @@ class InterfaceTestCase(base.FunctionalTest): if not networktype: interface = dbutils.create_test_interface(ifname=ifname, forihostid=host.id, - ihost_uuid=host.uuid) + ihost_uuid=host.uuid, + networks=networks) interface_uuid = interface.uuid else: interface = dbutils.post_get_test_interface( ifname=ifname, + ifclass=ifclass, networktype=networktype, + networks=networks, providernetworks=providernetworks, forihostid=host.id, ihost_uuid=host.uuid) @@ -296,8 +318,13 @@ class InterfaceTestCase(base.FunctionalTest): return port, interface - def _create_bond(self, ifname, networktype=None, + def _create_bond(self, ifname, networktype=None, ifclass=None, providernetworks=None, host=None, expect_errors=False): + if not isinstance(networktype, list): + networktypelist = [networktype] + else: + networktypelist = networktype + networktype = ','.join(networktype) if not host: host = self.controller port1, iface1 = self._create_ethernet(host=host) @@ -305,11 +332,23 @@ class InterfaceTestCase(base.FunctionalTest): interface_id = len(self.profile['interfaces']) if not ifname: ifname = (networktype or 'eth') + str(interface_id) + networks = [] + if all(network_type in constants.PLATFORM_NETWORK_TYPES + for network_type in networktypelist): + dbapi = db_api.get_instance() + ifclass = constants.INTERFACE_CLASS_PLATFORM + for network_type in networktypelist: + network = dbapi.network_get_by_type(network_type) + networks.append(str(network.id)) + if not ifclass and networktype: + ifclass = networktype interface = dbutils.post_get_test_interface( id=interface_id, ifname=ifname, iftype=constants.INTERFACE_TYPE_AE, + ifclass=ifclass, networktype=networktype, + networks=networks, uses=[iface1['ifname'], iface2['ifname']], txhashpolicy='layer2', providernetworks=providernetworks, @@ -332,24 +371,41 @@ class InterfaceTestCase(base.FunctionalTest): self.profile['interfaces'].append(interface) return interface - def _create_compute_bond(self, ifname, networktype=None, + def _create_compute_bond(self, ifname, networktype=None, ifclass=None, providernetworks=None, expect_errors=False): - return self._create_bond(ifname, networktype, providernetworks, + return self._create_bond(ifname, networktype, ifclass, providernetworks, self.compute, expect_errors) - def _create_vlan(self, ifname, networktype, vlan_id, + def _create_vlan(self, ifname, networktype, ifclass, vlan_id, lower_iface=None, providernetworks=None, host=None, expect_errors=False): + if not isinstance(networktype, list): + networktypelist = [networktype] + else: + networktypelist = networktype + networktype = ','.join(networktype) if not host: host = self.controller if not lower_iface: lower_port, lower_iface = self._create_ethernet(host=host) if not ifname: ifname = 'vlan' + str(vlan_id) + networks = [] + if all(network_type in constants.PLATFORM_NETWORK_TYPES + for network_type in networktypelist): + dbapi = db_api.get_instance() + ifclass = constants.INTERFACE_CLASS_PLATFORM + for network_type in networktypelist: + network = dbapi.network_get_by_type(network_type) + networks.append(str(network.id)) + if not ifclass and networktype: + ifclass = networktype interface = dbutils.post_get_test_interface( ifname=ifname, iftype=constants.INTERFACE_TYPE_VLAN, + ifclass=ifclass, networktype=networktype, + networks=networks, vlan_id=vlan_id, uses=[lower_iface['ifname']], providernetworks=providernetworks, @@ -359,10 +415,11 @@ class InterfaceTestCase(base.FunctionalTest): self.profile['interfaces'].append(interface) return interface - def _create_compute_vlan(self, ifname, networktype, vlan_id, + def _create_compute_vlan(self, ifname, networktype, ifclass, vlan_id, lower_iface=None, providernetworks=None, host=None, expect_errors=False): - return self._create_vlan(ifname, networktype, vlan_id, lower_iface, + return self._create_vlan(ifname, networktype, ifclass, vlan_id, + lower_iface, providernetworks, self.compute, expect_errors) def _post_and_check_success(self, ndict): @@ -421,7 +478,8 @@ class InterfaceTestCase(base.FunctionalTest): 'interfaces': [], 'ports': [], 'addresses': [], - 'routes': []} + 'routes': [], + 'interface_networks': []} self.system = None self.controller = None self.compute = None @@ -474,9 +532,12 @@ class InterfaceControllerVlanOverBond(InterfaceTestCase): # vlan interfaces over aggregated ethernet interfaces self._create_host(constants.CONTROLLER, admin=constants.ADMIN_LOCKED) bond = self._create_bond('pxeboot', constants.NETWORK_TYPE_PXEBOOT) - self._create_vlan('oam', constants.NETWORK_TYPE_OAM, 1, bond) - self._create_vlan('mgmt', constants.NETWORK_TYPE_MGMT, 2, bond) - self._create_vlan('infra', constants.NETWORK_TYPE_INFRA, 3, bond) + self._create_vlan('oam', constants.NETWORK_TYPE_OAM, + constants.INTERFACE_CLASS_PLATFORM, 1, bond) + self._create_vlan('mgmt', constants.NETWORK_TYPE_MGMT, + constants.INTERFACE_CLASS_PLATFORM, 2, bond) + self._create_vlan('infra', constants.NETWORK_TYPE_INFRA, + constants.INTERFACE_CLASS_PLATFORM, 3, bond) # self._create_ethernet('none') def setUp(self): @@ -494,9 +555,12 @@ class InterfaceControllerVlanOverEthernet(InterfaceTestCase): self._create_host(constants.CONTROLLER, admin=constants.ADMIN_LOCKED) port, iface = self._create_ethernet( 'pxeboot', constants.NETWORK_TYPE_PXEBOOT) - self._create_vlan('oam', constants.NETWORK_TYPE_OAM, 1, iface) - self._create_vlan('mgmt', constants.NETWORK_TYPE_MGMT, 2, iface) - self._create_vlan('infra', constants.NETWORK_TYPE_INFRA, 3, iface) + self._create_vlan('oam', constants.NETWORK_TYPE_OAM, + constants.INTERFACE_CLASS_PLATFORM, 1, iface) + self._create_vlan('mgmt', constants.NETWORK_TYPE_MGMT, + constants.INTERFACE_CLASS_PLATFORM, 2, iface) + self._create_vlan('infra', constants.NETWORK_TYPE_INFRA, + constants.INTERFACE_CLASS_PLATFORM, 3, iface) # self._create_ethernet_profile('none') def setUp(self): @@ -524,24 +588,34 @@ class InterfaceComputeEthernet(InterfaceTestCase): host=self.compute) self._create_ethernet('infra', constants.NETWORK_TYPE_INFRA, host=self.compute) - # self._create_ethernet('vrs', constants.NETWORK_TYPE_DATA_VRS, - # host=self.compute) - self._create_ethernet('data', constants.NETWORK_TYPE_DATA, + self._create_ethernet('data', + constants.NETWORK_TYPE_DATA, + constants.INTERFACE_CLASS_DATA, 'group0-data0', host=self.compute) - self._create_ethernet('sriov', constants.NETWORK_TYPE_PCI_SRIOV, + self._create_ethernet('sriov', + constants.NETWORK_TYPE_PCI_SRIOV, + constants.INTERFACE_CLASS_PCI_SRIOV, 'group0-data1', host=self.compute) - self._create_ethernet('pthru', constants.NETWORK_TYPE_PCI_PASSTHROUGH, + self._create_ethernet('pthru', + constants.NETWORK_TYPE_PCI_PASSTHROUGH, + constants.INTERFACE_CLASS_PCI_PASSTHROUGH, 'group0-ext0', host=self.compute) port, iface = ( - self._create_ethernet('slow', constants.NETWORK_TYPE_DATA, + self._create_ethernet('slow', + constants.NETWORK_TYPE_DATA, + constants.INTERFACE_CLASS_DATA, 'group0-ext1', host=self.compute)) port['dpdksupport'] = False port, iface = ( - self._create_ethernet('mlx4', constants.NETWORK_TYPE_DATA, + self._create_ethernet('mlx4', + constants.NETWORK_TYPE_DATA, + constants.INTERFACE_CLASS_DATA, 'group0-ext2', host=self.compute)) port['driver'] = 'mlx4_core' port, iface = ( - self._create_ethernet('mlx5', constants.NETWORK_TYPE_DATA, + self._create_ethernet('mlx5', + constants.NETWORK_TYPE_DATA, + constants.INTERFACE_CLASS_DATA, 'group0-ext3', host=self.compute)) port['driver'] = 'mlx5_core' @@ -561,9 +635,12 @@ class InterfaceComputeVlanOverEthernet(InterfaceTestCase): self._create_host(constants.CONTROLLER) port, iface = self._create_ethernet( 'pxeboot', constants.NETWORK_TYPE_PXEBOOT) - self._create_vlan('oam', constants.NETWORK_TYPE_OAM, 1, iface) - self._create_vlan('mgmt', constants.NETWORK_TYPE_MGMT, 2, iface) - self._create_vlan('infra', constants.NETWORK_TYPE_INFRA, 3, iface) + self._create_vlan('oam', constants.NETWORK_TYPE_OAM, + constants.INTERFACE_CLASS_PLATFORM, 1, iface) + self._create_vlan('mgmt', constants.NETWORK_TYPE_MGMT, + constants.INTERFACE_CLASS_PLATFORM, 2, iface) + self._create_vlan('infra', constants.NETWORK_TYPE_INFRA, + constants.INTERFACE_CLASS_PLATFORM, 3, iface) # Setup a sample configuration where the personality is set to a # compute and all interfaces are vlan interfaces over ethernet @@ -571,14 +648,20 @@ class InterfaceComputeVlanOverEthernet(InterfaceTestCase): self._create_host(constants.COMPUTE, admin=constants.ADMIN_LOCKED) port, iface = self._create_ethernet( 'pxeboot', constants.NETWORK_TYPE_PXEBOOT, host=self.compute) - self._create_compute_vlan('mgmt', constants.NETWORK_TYPE_MGMT, 2, iface) - self._create_compute_vlan('infra', constants.NETWORK_TYPE_INFRA, 3) - # self._create_vlan('vrs', constants.NETWORK_TYPE_DATA_VRS, 4, host=self.compute) - self._create_compute_vlan('data', constants.NETWORK_TYPE_DATA, 5, + self._create_compute_vlan('mgmt', constants.NETWORK_TYPE_MGMT, + constants.INTERFACE_CLASS_PLATFORM, 2, iface) + self._create_compute_vlan('infra', constants.NETWORK_TYPE_INFRA, + constants.INTERFACE_CLASS_PLATFORM, 3) + self._create_compute_vlan('data', constants.INTERFACE_CLASS_DATA, + constants.NETWORK_TYPE_DATA, 5, providernetworks='group0-ext0') - self._create_ethernet('sriov', constants.NETWORK_TYPE_PCI_SRIOV, + self._create_ethernet('sriov', + constants.NETWORK_TYPE_PCI_SRIOV, + constants.INTERFACE_CLASS_PCI_SRIOV, 'group0-data0', host=self.compute) - self._create_ethernet('pthru', constants.NETWORK_TYPE_PCI_PASSTHROUGH, + self._create_ethernet('pthru', + constants.NETWORK_TYPE_PCI_PASSTHROUGH, + constants.INTERFACE_CLASS_PCI_PASSTHROUGH, 'group0-data1', host=self.compute) def setUp(self): @@ -603,12 +686,17 @@ class InterfaceComputeBond(InterfaceTestCase): self._create_host(constants.COMPUTE, admin=constants.ADMIN_LOCKED) self._create_compute_bond('mgmt', constants.NETWORK_TYPE_MGMT) self._create_compute_bond('infra', constants.NETWORK_TYPE_INFRA) - # self._create_bond('vrs', constants.NETWORK_TYPE_DATA_VRS, host=self.compute) - self._create_compute_bond('data', constants.NETWORK_TYPE_DATA, + self._create_compute_bond('data', + constants.NETWORK_TYPE_DATA, + constants.INTERFACE_CLASS_DATA, providernetworks='group0-data0') - self._create_ethernet('sriov', constants.NETWORK_TYPE_PCI_SRIOV, + self._create_ethernet('sriov', + constants.NETWORK_TYPE_PCI_SRIOV, + constants.INTERFACE_CLASS_PCI_SRIOV, 'group0-ext0', host=self.compute) - self._create_ethernet('pthru', constants.NETWORK_TYPE_PCI_PASSTHROUGH, + self._create_ethernet('pthru', + constants.NETWORK_TYPE_PCI_PASSTHROUGH, + constants.INTERFACE_CLASS_PCI_PASSTHROUGH, 'group0-ext1', host=self.compute) def setUp(self): @@ -622,33 +710,43 @@ class InterfaceComputeVlanOverBond(InterfaceTestCase): def _setup_configuration(self): self._create_host(constants.CONTROLLER) - bond = self._create_bond('pxeboot', constants.NETWORK_TYPE_PXEBOOT) - self._create_vlan('oam', constants.NETWORK_TYPE_OAM, 1, bond) - self._create_vlan('mgmt', constants.NETWORK_TYPE_MGMT, 2, bond) - self._create_vlan('infra', constants.NETWORK_TYPE_INFRA, 3, bond) + bond = self._create_bond('pxeboot', constants.NETWORK_TYPE_PXEBOOT, + constants.INTERFACE_CLASS_PLATFORM) + self._create_vlan('oam', constants.NETWORK_TYPE_OAM, + constants.INTERFACE_CLASS_PLATFORM, 1, bond) + self._create_vlan('mgmt', constants.NETWORK_TYPE_MGMT, + constants.INTERFACE_CLASS_PLATFORM, 2, bond) + self._create_vlan('infra', constants.NETWORK_TYPE_INFRA, + constants.INTERFACE_CLASS_PLATFORM, 3, bond) # Setup a sample configuration where the personality is set to a # compute and all interfaces are vlan interfaces over aggregated # ethernet interfaces. self._create_host(constants.COMPUTE, admin=constants.ADMIN_LOCKED) bond = self._create_compute_bond('pxeboot', - constants.NETWORK_TYPE_PXEBOOT) - self._create_compute_vlan('mgmt', constants.NETWORK_TYPE_MGMT, 2, bond) - self._create_compute_vlan('infra', constants.NETWORK_TYPE_INFRA, 3, + constants.NETWORK_TYPE_PXEBOOT, + constants.INTERFACE_CLASS_PLATFORM) + self._create_compute_vlan('mgmt', constants.NETWORK_TYPE_MGMT, + constants.INTERFACE_CLASS_PLATFORM, 2, bond) + self._create_compute_vlan('infra', constants.NETWORK_TYPE_INFRA, + constants.INTERFACE_CLASS_PLATFORM, 3, bond) - # bond1 = self._create_bond('bond3', providernetworks='group0-data0', - # host=self.compute) - # self._create_vlan('vrs', constants.NETWORK_TYPE_DATA_VRS, 4, bond1, - # host=self.compute) bond2 = self._create_compute_bond('bond2', constants.NETWORK_TYPE_NONE) - self._create_compute_vlan('data', constants.NETWORK_TYPE_DATA, 5, bond2, + self._create_compute_vlan('data', + constants.NETWORK_TYPE_DATA, + constants.INTERFACE_CLASS_DATA, + 5, bond2, providernetworks='group0-ext0') self._create_compute_bond('bond3', constants.NETWORK_TYPE_NONE) - self._create_ethernet('sriov', constants.NETWORK_TYPE_PCI_SRIOV, + self._create_ethernet('sriov', + constants.NETWORK_TYPE_PCI_SRIOV, + constants.INTERFACE_CLASS_PCI_SRIOV, 'group0-data0', host=self.compute) - self._create_ethernet('pthru', constants.NETWORK_TYPE_PCI_PASSTHROUGH, + self._create_ethernet('pthru', + constants.NETWORK_TYPE_PCI_PASSTHROUGH, + constants.INTERFACE_CLASS_PCI_PASSTHROUGH, 'group0-data1', host=self.compute) def setUp(self): @@ -663,7 +761,8 @@ class InterfaceComputeVlanOverDataEthernet(InterfaceTestCase): def _setup_configuration(self): self._create_host(constants.CONTROLLER) bond = self._create_bond('pxeboot', constants.NETWORK_TYPE_PXEBOOT) - self._create_vlan('oam', constants.NETWORK_TYPE_OAM, 1, bond) + self._create_vlan('oam', constants.NETWORK_TYPE_OAM, + constants.INTERFACE_CLASS_PLATFORM, 1, bond) self._create_ethernet('mgmt', constants.NETWORK_TYPE_MGMT) self._create_ethernet('infra', constants.NETWORK_TYPE_INFRA) @@ -673,20 +772,23 @@ class InterfaceComputeVlanOverDataEthernet(InterfaceTestCase): self._create_host(constants.COMPUTE, admin=constants.ADMIN_LOCKED) port, iface = ( self._create_ethernet('data', - [constants.NETWORK_TYPE_DATA], + constants.NETWORK_TYPE_DATA, + constants.INTERFACE_CLASS_DATA, 'group0-data0', host=self.compute)) self._create_ethernet('mgmt', constants.NETWORK_TYPE_MGMT, host=self.compute) self._create_ethernet('infra', constants.NETWORK_TYPE_INFRA, host=self.compute) - - # self._create_vlan('vrs', constants.NETWORK_TYPE_DATA_VRS, 4, - # lower_iface=iface, host=self.compute) - self._create_compute_vlan('data2', constants.NETWORK_TYPE_DATA, 5, + self._create_compute_vlan('data2', constants.NETWORK_TYPE_DATA, + constants.INTERFACE_CLASS_DATA, 5, iface, providernetworks='group0-ext0') - self._create_ethernet('sriov', constants.NETWORK_TYPE_PCI_SRIOV, + self._create_ethernet('sriov', + constants.NETWORK_TYPE_PCI_SRIOV, + constants.INTERFACE_CLASS_PCI_SRIOV, 'group0-ext1', host=self.compute) - self._create_ethernet('pthru', constants.NETWORK_TYPE_PCI_PASSTHROUGH, + self._create_ethernet('pthru', + constants.NETWORK_TYPE_PCI_PASSTHROUGH, + constants.INTERFACE_CLASS_PCI_PASSTHROUGH, 'group0-ext2', host=self.compute) def setUp(self): @@ -707,27 +809,28 @@ class InterfaceCpeEthernet(InterfaceTestCase): self._create_ethernet('oam', constants.NETWORK_TYPE_OAM) self._create_ethernet('mgmt', constants.NETWORK_TYPE_MGMT) self._create_ethernet('infra', constants.NETWORK_TYPE_INFRA) - # self._create_ethernet('vrs', constants.NETWORK_TYPE_DATA_VRS) self._create_ethernet('data', constants.NETWORK_TYPE_DATA, + constants.INTERFACE_CLASS_DATA, 'group0-data0') self._create_ethernet('sriov', constants.NETWORK_TYPE_PCI_SRIOV, + constants.INTERFACE_CLASS_PCI_SRIOV, 'group0-data1') self._create_ethernet('pthru', constants.NETWORK_TYPE_PCI_PASSTHROUGH, - 'group0-ext0') - self._create_ethernet('ptsriov', - constants.NETWORK_TYPE_PCI_PASSTHROUGH + ',' + - constants.NETWORK_TYPE_PCI_SRIOV, + constants.INTERFACE_CLASS_PCI_PASSTHROUGH, 'group0-ext0') port, iface = ( self._create_ethernet('slow', constants.NETWORK_TYPE_DATA, + constants.INTERFACE_CLASS_DATA, 'group0-ext1')) port['dpdksupport'] = False port, iface = ( self._create_ethernet('mlx4', constants.NETWORK_TYPE_DATA, + constants.INTERFACE_CLASS_DATA, 'group0-ext2')) port['driver'] = 'mlx4_core' port, iface = ( self._create_ethernet('mlx5', constants.NETWORK_TYPE_DATA, + constants.INTERFACE_CLASS_DATA, 'group0-ext3')) def setUp(self): @@ -747,16 +850,20 @@ class InterfaceCpeVlanOverEthernet(InterfaceTestCase): admin=constants.ADMIN_LOCKED) port, iface = self._create_ethernet( 'pxeboot', constants.NETWORK_TYPE_PXEBOOT) - self._create_vlan('oam', constants.NETWORK_TYPE_OAM, 1, iface) - self._create_vlan('mgmt', constants.NETWORK_TYPE_MGMT, 2, iface) - self._create_vlan('infra', constants.NETWORK_TYPE_INFRA, 3) - # self._create_vlan('vrs', constants.NETWORK_TYPE_DATA_VRS, 4) - + self._create_vlan('oam', constants.NETWORK_TYPE_OAM, + constants.INTERFACE_CLASS_PLATFORM, 1, iface) + self._create_vlan('mgmt', constants.NETWORK_TYPE_MGMT, + constants.INTERFACE_CLASS_PLATFORM, 2, iface) + self._create_vlan('infra', constants.NETWORK_TYPE_INFRA, + constants.INTERFACE_CLASS_PLATFORM, 3) self._create_ethernet('data', constants.NETWORK_TYPE_DATA, + constants.INTERFACE_CLASS_DATA, providernetworks='group0-ext0') self._create_ethernet('sriov', constants.NETWORK_TYPE_PCI_SRIOV, + constants.INTERFACE_CLASS_PCI_SRIOV, 'group0-ext1') self._create_ethernet('pthru', constants.NETWORK_TYPE_PCI_PASSTHROUGH, + constants.INTERFACE_CLASS_PCI_PASSTHROUGH, 'group0-ext2') def setUp(self): @@ -778,12 +885,14 @@ class InterfaceCpeBond(InterfaceTestCase): self._create_bond('oam', constants.NETWORK_TYPE_OAM) self._create_bond('mgmt', constants.NETWORK_TYPE_MGMT) self._create_bond('infra', constants.NETWORK_TYPE_INFRA) - # self._create_bond('vrs', constants.NETWORK_TYPE_DATA_VRS) self._create_bond('data', constants.NETWORK_TYPE_DATA, + constants.INTERFACE_CLASS_DATA, providernetworks='group0-data0') self._create_ethernet('sriov', constants.NETWORK_TYPE_PCI_SRIOV, + constants.INTERFACE_CLASS_PCI_SRIOV, providernetworks='group0-ext0') self._create_ethernet('pthru', constants.NETWORK_TYPE_PCI_PASSTHROUGH, + constants.INTERFACE_CLASS_PCI_PASSTHROUGH, providernetworks='group0-ext1') def setUp(self): @@ -802,17 +911,22 @@ class InterfaceCpeVlanOverBond(InterfaceTestCase): self._create_host(constants.CONTROLLER, constants.COMPUTE, admin=constants.ADMIN_LOCKED) bond = self._create_bond('pxeboot', constants.NETWORK_TYPE_PXEBOOT) - self._create_vlan('oam', constants.NETWORK_TYPE_OAM, 1, bond) - self._create_vlan('mgmt', constants.NETWORK_TYPE_MGMT, 2, bond) - self._create_vlan('infra', constants.NETWORK_TYPE_INFRA, 3, bond) - # bond1 = self._create_bond('bond3') - # self._create_vlan('vrs', constants.NETWORK_TYPE_DATA_VRS, 4, bond1) + self._create_vlan('oam', constants.NETWORK_TYPE_OAM, + constants.INTERFACE_CLASS_PLATFORM, 1, bond) + self._create_vlan('mgmt', constants.NETWORK_TYPE_MGMT, + constants.INTERFACE_CLASS_PLATFORM, 2, bond) + self._create_vlan('infra', constants.NETWORK_TYPE_INFRA, + constants.INTERFACE_CLASS_PLATFORM, 3, bond) bond2 = self._create_bond('bond4', constants.NETWORK_TYPE_NONE) - self._create_vlan('data', constants.NETWORK_TYPE_DATA, 5, bond2, + self._create_vlan('data', constants.NETWORK_TYPE_DATA, + constants.INTERFACE_CLASS_DATA, + 5, bond2, providernetworks='group0-ext0') self._create_ethernet('sriov', constants.NETWORK_TYPE_PCI_SRIOV, + constants.INTERFACE_CLASS_PCI_SRIOV, 'group0-ext1') self._create_ethernet('pthru', constants.NETWORK_TYPE_PCI_PASSTHROUGH, + constants.INTERFACE_CLASS_PCI_PASSTHROUGH, 'group0-ext2') def setUp(self): @@ -834,21 +948,28 @@ class InterfaceCpeVlanOverDataEthernet(InterfaceTestCase): port, iface = ( self._create_ethernet('data', constants.NETWORK_TYPE_DATA, + constants.INTERFACE_CLASS_DATA, 'group0-data0')) - self._create_vlan('oam', constants.NETWORK_TYPE_OAM, 1, iface, + self._create_vlan('oam', constants.NETWORK_TYPE_OAM, + constants.INTERFACE_CLASS_PLATFORM, 1, iface, expect_errors=True) - self._create_vlan('mgmt', constants.NETWORK_TYPE_MGMT, 2, iface, + self._create_vlan('mgmt', constants.NETWORK_TYPE_MGMT, + constants.INTERFACE_CLASS_PLATFORM, 2, iface, expect_errors=True) - self._create_vlan('infra', constants.NETWORK_TYPE_INFRA, 3, iface, + self._create_vlan('infra', constants.NETWORK_TYPE_INFRA, + constants.INTERFACE_CLASS_PLATFORM, 3, iface, expect_errors=True) - # self._create_vlan('vrs', constants.NETWORK_TYPE_DATA_VRS, 4, iface) - self._create_vlan('data2', constants.NETWORK_TYPE_DATA, 5, iface, + self._create_vlan('data2', constants.NETWORK_TYPE_DATA, + constants.INTERFACE_CLASS_DATA, + 5, iface, providernetworks='group0-ext0', expect_errors=False) self._create_ethernet('sriov', constants.NETWORK_TYPE_PCI_SRIOV, + ifclass=constants.INTERFACE_CLASS_PCI_SRIOV, providernetworks='group0-ext1', expect_errors=False) self._create_ethernet('pthru', constants.NETWORK_TYPE_PCI_PASSTHROUGH, + ifclass=constants.INTERFACE_CLASS_PCI_PASSTHROUGH, providernetworks='group0-ext2', expect_errors=False) @@ -899,6 +1020,7 @@ class TestPatch(InterfaceTestCase): def test_interface_usesmodify_success(self): data_bond = self._create_bond('data', constants.NETWORK_TYPE_DATA, + constants.INTERFACE_CLASS_DATA, providernetworks='group0-data0', host=self.compute) @@ -922,6 +1044,7 @@ class TestPatch(InterfaceTestCase): ihost_uuid=self.compute.uuid, ifname='data0', networktype=constants.NETWORK_TYPE_DATA, + ifclass=constants.INTERFACE_CLASS_DATA, iftype=constants.INTERFACE_TYPE_ETHERNET, providernetworks='group0-data0', aemode='balanced', @@ -945,6 +1068,7 @@ class TestPatch(InterfaceTestCase): ihost_uuid=self.compute.uuid, ifname='data0', networktype=constants.NETWORK_TYPE_DATA, + ifclass=constants.INTERFACE_CLASS_DATA, iftype=constants.INTERFACE_TYPE_VLAN, vlan_id=100, providernetworks='group0-ext0', @@ -959,17 +1083,18 @@ class TestPatch(InterfaceTestCase): self.assertEqual('application/json', response.content_type) self.assertTrue(response.json['error_message']) + # No longer requires setting the network type back to none # Expected error: The network type of an interface cannot be changed without # first being reset back to none - def test_invalid_change_networktype(self): - port, interface = self._create_ethernet('oam', - constants.NETWORK_TYPE_OAM) - response = self.patch_dict_json( - '%s' % self._get_path(interface['uuid']), - networktype=constants.NETWORK_TYPE_MGMT, expect_errors=True) - self.assertEqual(http_client.BAD_REQUEST, response.status_int) - self.assertEqual('application/json', response.content_type) - self.assertTrue(response.json['error_message']) + # def test_invalid_change_networktype(self): + # port, interface = self._create_ethernet('oam', + # constants.NETWORK_TYPE_OAM) + # response = self.patch_dict_json( + # '%s' % self._get_path(interface['uuid']), + # networktype=constants.NETWORK_TYPE_MGMT, expect_errors=True) + # self.assertEqual(http_client.BAD_REQUEST, response.status_int) + # self.assertEqual('application/json', response.content_type) + # self.assertTrue(response.json['error_message']) class TestPost(InterfaceTestCase): @@ -981,36 +1106,42 @@ class TestPost(InterfaceTestCase): # Expected error: The oam network type is only supported on controller nodes def test_invalid_oam_on_compute(self): self._create_ethernet('oam', constants.NETWORK_TYPE_OAM, + constants.INTERFACE_CLASS_PLATFORM, host=self.compute, expect_errors=True) # Expected error: The pci-passthrough, pci-sriov network types are only # valid on Ethernet interfaces def test_invalid_iftype_for_pci_network_type(self): self._create_bond('pthru', constants.NETWORK_TYPE_PCI_PASSTHROUGH, + ifclass=constants.INTERFACE_CLASS_PCI_PASSTHROUGH, host=self.compute, expect_errors=True) # Expected error: The ___ network type is only supported on nodes supporting # compute functions def test_invalid_network_type_on_noncompute(self): self._create_ethernet('data0', constants.NETWORK_TYPE_DATA, + ifclass=constants.INTERFACE_CLASS_DATA, providernetworks='group0-ext0', expect_errors=True) # Expected error: Interface name cannot be whitespace. def test_invalid_whitespace_interface_name(self): self._create_ethernet(' ', constants.NETWORK_TYPE_DATA, + ifclass=constants.INTERFACE_CLASS_DATA, providernetworks='group0-ext0', expect_errors=True) # Expected error: Interface name must be in lower case. def test_invalid_uppercase_interface_name(self): self._create_ethernet('miXedCaSe', constants.NETWORK_TYPE_DATA, + ifclass=constants.INTERFACE_CLASS_DATA, providernetworks='group0-ext0', expect_errors=True) # Expected error: Cannot use special characters in interface name. def test_invalid_character_interface_name(self): self._create_ethernet('bad-name', constants.NETWORK_TYPE_DATA, + ifclass=constants.INTERFACE_CLASS_DATA, providernetworks='group0-ext0', expect_errors=True) @@ -1022,9 +1153,11 @@ class TestPost(InterfaceTestCase): # Expected message: Name must be unique def test_create_duplicate_interface_name(self): self._create_ethernet('data0', constants.NETWORK_TYPE_DATA, + ifclass=constants.INTERFACE_CLASS_DATA, providernetworks='group0-data0', host=self.compute) self._create_ethernet('data0', constants.NETWORK_TYPE_DATA, + ifclass=constants.INTERFACE_CLASS_DATA, providernetworks='group0-ext0', host=self.compute, expect_errors=True) @@ -1034,6 +1167,8 @@ class TestPost(InterfaceTestCase): ihost_uuid=self.controller.uuid, ifname='name', networktype=constants.NETWORK_TYPE_MGMT, + networks=['1'], + ifclass=constants.INTERFACE_CLASS_PLATFORM, iftype=constants.INTERFACE_TYPE_ETHERNET, ipv4_mode=constants.IPV4_POOL, ipv4_pool=self.address_pool1.uuid) @@ -1046,6 +1181,7 @@ class TestPost(InterfaceTestCase): ihost_uuid=self.compute.uuid, ifname='name', networktype=constants.NETWORK_TYPE_PCI_PASSTHROUGH, + ifclass=constants.INTERFACE_CLASS_PCI_PASSTHROUGH, iftype=constants.INTERFACE_TYPE_ETHERNET, ipv4_mode=constants.IPV4_STATIC, ipv6_mode=constants.IPV6_STATIC, @@ -1060,6 +1196,8 @@ class TestPost(InterfaceTestCase): ihost_uuid=self.controller.uuid, ifname='name', networktype=constants.NETWORK_TYPE_INFRA, + networks=['2'], + ifclass=constants.INTERFACE_CLASS_PLATFORM, iftype=constants.INTERFACE_TYPE_ETHERNET, ipv4_mode=constants.IPV4_DISABLED, ipv6_mode=constants.IPV6_DISABLED, @@ -1073,6 +1211,8 @@ class TestPost(InterfaceTestCase): ihost_uuid=self.controller.uuid, ifname='name', networktype=constants.NETWORK_TYPE_MGMT, + networks=['1'], + ifclass=constants.INTERFACE_CLASS_PLATFORM, iftype=constants.INTERFACE_TYPE_ETHERNET, ipv4_mode=constants.IPV4_DISABLED, ipv4_pool=self.address_pool1.uuid) @@ -1085,6 +1225,8 @@ class TestPost(InterfaceTestCase): ihost_uuid=self.controller.uuid, ifname='name', networktype=constants.NETWORK_TYPE_MGMT, + networks=['1'], + ifclass=constants.INTERFACE_CLASS_PLATFORM, iftype=constants.INTERFACE_TYPE_ETHERNET, ipv6_mode=constants.IPV6_DISABLED, ipv6_pool=self.address_pool1.uuid) @@ -1096,6 +1238,8 @@ class TestPost(InterfaceTestCase): ihost_uuid=self.compute.uuid, ifname='name', networktype=constants.NETWORK_TYPE_MGMT, + networks=['1'], + ifclass=constants.INTERFACE_CLASS_PLATFORM, iftype=constants.INTERFACE_TYPE_ETHERNET, ipv4_mode=constants.IPV4_POOL, ipv6_mode=constants.IPV6_POOL) @@ -1107,6 +1251,8 @@ class TestPost(InterfaceTestCase): ihost_uuid=self.compute.uuid, ifname='name', networktype=constants.NETWORK_TYPE_MGMT, + networks=['1'], + ifclass=constants.INTERFACE_CLASS_PLATFORM, iftype=constants.INTERFACE_TYPE_ETHERNET, ipv4_mode=constants.IPV4_POOL, ipv6_mode=constants.IPV6_POOL, @@ -1119,6 +1265,8 @@ class TestPost(InterfaceTestCase): ihost_uuid=self.compute.uuid, ifname='name', networktype=constants.NETWORK_TYPE_MGMT, + networks=['1'], + ifclass=constants.INTERFACE_CLASS_PLATFORM, iftype=constants.INTERFACE_TYPE_ETHERNET, ipv4_mode=constants.IPV4_POOL, ipv6_mode=constants.IPV6_POOL, @@ -1132,6 +1280,8 @@ class TestPost(InterfaceTestCase): ihost_uuid=self.compute.uuid, ifname='name', networktype=constants.NETWORK_TYPE_MGMT, + networks=['1'], + ifclass=constants.INTERFACE_CLASS_PLATFORM, iftype=constants.INTERFACE_TYPE_ETHERNET, ipv4_mode=constants.IPV4_POOL, ipv6_mode=constants.IPV6_POOL, @@ -1147,6 +1297,7 @@ class TestPost(InterfaceTestCase): providernetworks='group0-data0', ifname='name', networktype=constants.NETWORK_TYPE_DATA, + ifclass=constants.INTERFACE_CLASS_DATA, iftype='AE', aemode='active_standby', txhashpolicy='layer2') @@ -1160,6 +1311,7 @@ class TestPost(InterfaceTestCase): providernetworks='group0-data0', ifname='name', networktype=constants.NETWORK_TYPE_DATA, + ifclass=constants.INTERFACE_CLASS_DATA, iftype=constants.INTERFACE_TYPE_AE, aemode='active_standby', txhashpolicy='layer2') @@ -1172,6 +1324,7 @@ class TestPost(InterfaceTestCase): ihost_uuid=self.compute.uuid, ifname='name', networktype=constants.NETWORK_TYPE_DATA, + ifclass=constants.INTERFACE_CLASS_DATA, iftype=constants.INTERFACE_TYPE_AE, aemode='balanced', txhashpolicy='layer2+3') @@ -1185,6 +1338,7 @@ class TestPost(InterfaceTestCase): providernetworks='group0-data0', ifname='name', networktype=constants.NETWORK_TYPE_DATA, + ifclass=constants.INTERFACE_CLASS_DATA, iftype=constants.INTERFACE_TYPE_AE, aemode='802.3ad', txhashpolicy=None) @@ -1195,6 +1349,7 @@ class TestPost(InterfaceTestCase): providernetworks='group0-data0', ifname='name', networktype=constants.NETWORK_TYPE_DATA, + ifclass=constants.INTERFACE_CLASS_DATA, iftype=constants.INTERFACE_TYPE_AE, aemode='balanced', txhashpolicy=None) @@ -1208,6 +1363,8 @@ class TestPost(InterfaceTestCase): providernetworks='group0-data0', ifname='name', networktype=constants.NETWORK_TYPE_MGMT, + networks=['1'], + ifclass=constants.INTERFACE_CLASS_PLATFORM, iftype=constants.INTERFACE_TYPE_AE, aemode='balanced', txhashpolicy='layer2') @@ -1222,6 +1379,7 @@ class TestPost(InterfaceTestCase): providernetworks='group0-data0', ifname='name', networktype=constants.NETWORK_TYPE_DATA, + ifclass=constants.INTERFACE_CLASS_DATA, iftype=constants.INTERFACE_TYPE_AE, aemode='bad_aemode', txhashpolicy='layer2') @@ -1232,6 +1390,8 @@ class TestPost(InterfaceTestCase): ihost_uuid=self.controller.uuid, ifname='name', networktype=constants.NETWORK_TYPE_OAM, + networks=['3'], + ifclass=constants.INTERFACE_CLASS_PLATFORM, iftype=constants.INTERFACE_TYPE_AE, aemode='bad_aemode', txhashpolicy='layer2') @@ -1242,6 +1402,8 @@ class TestPost(InterfaceTestCase): ihost_uuid=self.compute.uuid, ifname='name', networktype=constants.NETWORK_TYPE_INFRA, + networks=['2'], + ifclass=constants.INTERFACE_CLASS_PLATFORM, iftype=constants.INTERFACE_TYPE_AE, aemode='bad_aemode', txhashpolicy='layer2') @@ -1254,36 +1416,42 @@ class TestPost(InterfaceTestCase): ihost_uuid=self.compute.uuid, ifname='name', networktype=constants.NETWORK_TYPE_INFRA, + networks=['2'], + ifclass=constants.INTERFACE_CLASS_PLATFORM, iftype=constants.INTERFACE_TYPE_ETHERNET, aemode='balanced', txhashpolicy='layer2') self._post_and_check_failure(ndict) - # Expected: Setting of ___ interface MTU is not supported - def test_setting_mgmt_mtu_disallowed(self): + def test_setting_mgmt_mtu_allowed(self): ndict = dbutils.post_get_test_interface( ihost_uuid=self.controller.uuid, ifname='mgmt0', networktype=constants.NETWORK_TYPE_MGMT, + networks=['1'], + ifclass=constants.INTERFACE_CLASS_PLATFORM, iftype=constants.INTERFACE_TYPE_ETHERNET, imtu=1600) - self._post_and_check_failure(ndict) + self._post_and_check_success(ndict) - # Expected: Setting of infra interface MTU is not supported - def test_setting_infra_mtu_disallowed(self): + def test_setting_infra_mtu_allowed(self): ndict = dbutils.post_get_test_interface( ihost_uuid=self.controller.uuid, ifname='infra0', networktype=constants.NETWORK_TYPE_INFRA, + networks=['2'], + ifclass=constants.INTERFACE_CLASS_PLATFORM, iftype=constants.INTERFACE_TYPE_ETHERNET, imtu=1600) - self._post_and_check_failure(ndict) + self._post_and_check_success(ndict) # Expected message: Interface eth0 is already used by another AE interface # bond0 def test_create_bond_invalid_overlap_ae(self): bond_iface = self._create_compute_bond('bond0', - constants.NETWORK_TYPE_DATA, providernetworks='group0-data0') + constants.NETWORK_TYPE_DATA, + constants.INTERFACE_CLASS_DATA, + providernetworks='group0-data0') port, iface1 = self._create_ethernet() ndict = dbutils.post_get_test_interface( @@ -1291,23 +1459,29 @@ class TestPost(InterfaceTestCase): providernetworks='group0-ext1', ifname='bond1', networktype=constants.NETWORK_TYPE_DATA, + ifclass=constants.INTERFACE_CLASS_DATA, iftype=constants.INTERFACE_TYPE_AE, aemode='balanced', txhashpolicy='layer2', - uses=[bond_iface['uses'][0], iface1.uuid]) + uses=[bond_iface['uses'][0], iface1['uuid']]) self._post_and_check_failure(ndict) # Expected message: VLAN id must be between 1 and 4094. def test_create_invalid_vlan_id(self): - self._create_compute_vlan('vlan0', constants.NETWORK_TYPE_DATA, 4095, + self._create_compute_vlan('vlan0', constants.NETWORK_TYPE_DATA, + ifclass=constants.INTERFACE_CLASS_DATA, + vlan_id=4095, providernetworks='group0-ext0', expect_errors=True) # Expected message: Interface eth0 is already used by another VLAN # interface vlan0 def test_create_bond_invalid_overlap_vlan(self): - vlan_iface = self._create_compute_vlan('vlan0', - constants.NETWORK_TYPE_DATA, 10, providernetworks='group0-ext0') + vlan_iface = self._create_compute_vlan( + 'vlan0', + constants.NETWORK_TYPE_DATA, + ifclass=constants.INTERFACE_CLASS_DATA, + vlan_id=10, providernetworks='group0-ext0') port, iface1 = self._create_ethernet() ndict = dbutils.post_get_test_interface( @@ -1315,16 +1489,19 @@ class TestPost(InterfaceTestCase): providernetworks='group0-ext1', ifname='bond0', networktype=constants.NETWORK_TYPE_DATA, + ifclass=constants.INTERFACE_CLASS_DATA, iftype=constants.INTERFACE_TYPE_AE, aemode='balanced', txhashpolicy='layer2', - uses=[vlan_iface['uses'][0], iface1.uuid]) + uses=[vlan_iface['uses'][0], iface1['uuid']]) self._post_and_check_failure(ndict) # Expected message: Can only have one interface for vlan type. def test_create_vlan_invalid_uses(self): bond_iface = self._create_compute_bond('bond0', - constants.NETWORK_TYPE_DATA, providernetworks='group0-data0') + constants.NETWORK_TYPE_DATA, + constants.INTERFACE_CLASS_DATA, + providernetworks='group0-data0') port, iface1 = self._create_ethernet() ndict = dbutils.post_get_test_interface( @@ -1332,30 +1509,37 @@ class TestPost(InterfaceTestCase): providernetworks='group0-ext1', ifname='bond1', networktype=constants.NETWORK_TYPE_DATA, + ifclass=constants.INTERFACE_CLASS_DATA, iftype=constants.INTERFACE_TYPE_VLAN, aemode='balanced', txhashpolicy='layer2', - uses=[bond_iface['uses'][0], iface1.uuid]) + uses=[bond_iface['uses'][0], iface1['uuid']]) self._post_and_check_failure(ndict) # Expected message: VLAN interfaces cannot be created over existing VLAN # interfaces def test_create_invalid_vlan_over_vlan(self): vlan_iface = self._create_compute_vlan( - 'vlan1', constants.NETWORK_TYPE_DATA, 1, + 'vlan1', constants.NETWORK_TYPE_DATA, + constants.INTERFACE_CLASS_DATA, 1, providernetworks='group0-ext0') self._create_compute_vlan('vlan2', - constants.NETWORK_TYPE_DATA, 2, - lower_iface=vlan_iface, providernetworks='group0-ext1', - expect_errors=True) + constants.NETWORK_TYPE_DATA, + constants.INTERFACE_CLASS_DATA, + vlan_id=2, + lower_iface=vlan_iface, + providernetworks='group0-ext1', + expect_errors=True) # Expected message: data VLAN cannot be created over a LAG interface with # network type pxeboot def test_create_data_vlan_over_pxeboot_lag(self): bond_iface = self._create_compute_bond( - 'pxeboot', constants.NETWORK_TYPE_PXEBOOT) - self._create_compute_vlan('vlan2', - constants.NETWORK_TYPE_DATA, 2, + 'pxeboot', constants.NETWORK_TYPE_PXEBOOT, + constants.INTERFACE_CLASS_PLATFORM) + self._create_compute_vlan( + 'vlan2', + constants.NETWORK_TYPE_DATA, constants.INTERFACE_CLASS_DATA, 2, lower_iface=bond_iface, providernetworks='group0-ext1', expect_errors=True) @@ -1363,9 +1547,11 @@ class TestPost(InterfaceTestCase): # network type mgmt def test_create_data_vlan_over_mgmt_lag(self): bond_iface = self._create_compute_bond( - 'mgmt', constants.NETWORK_TYPE_MGMT) + 'mgmt', constants.NETWORK_TYPE_MGMT, + constants.INTERFACE_CLASS_PLATFORM) self._create_compute_vlan( - 'vlan2', constants.NETWORK_TYPE_DATA, 2, + 'vlan2', constants.NETWORK_TYPE_DATA, + constants.INTERFACE_CLASS_DATA, 2, lower_iface=bond_iface, providernetworks='group0-ext1', expect_errors=True) @@ -1373,9 +1559,11 @@ class TestPost(InterfaceTestCase): # network type data def test_create_mgmt_vlan_over_data_lag(self): bond_iface = self._create_compute_bond( - 'data', constants.NETWORK_TYPE_DATA, providernetworks='group0-ext1') + 'data', constants.NETWORK_TYPE_DATA, + constants.INTERFACE_CLASS_DATA, providernetworks='group0-ext1') self._create_compute_vlan( - 'mgmt', constants.NETWORK_TYPE_MGMT, 2, + 'mgmt', constants.NETWORK_TYPE_MGMT, + constants.INTERFACE_CLASS_PLATFORM, 2, lower_iface=bond_iface, providernetworks='group0-ext1', expect_errors=True) @@ -1383,32 +1571,23 @@ class TestPost(InterfaceTestCase): # so the VLAN configured for the mgmt interface must match. def test_mgmt_vlan_not_matching_in_network(self): self._create_compute_vlan( - 'vlan2', constants.NETWORK_TYPE_MGMT, 12, + 'vlan2', constants.NETWORK_TYPE_MGMT, + constants.INTERFACE_CLASS_PLATFORM, 12, providernetworks='group0-ext1', expect_errors=True) - # Expected message: The management VLAN was not configured on this system, - # so configuring the %s interface over a VLAN is not allowed. - def test_mgmt_vlan_not_configured_in_network(self): - dbapi = db_api.get_instance() - mgmt_network = dbapi.network_get_by_type(constants.NETWORK_TYPE_MGMT) - values = {'vlan_id': None} - dbapi.network_update(mgmt_network.uuid, values) - self._create_compute_vlan( - 'vlan2', constants.NETWORK_TYPE_MGMT, 12, - providernetworks='group0-ext1', - expect_errors=True) - # Expected message: # Provider network(s) not supported for non-data interfaces. def test_create_nondata_provider_network(self): self._create_compute_bond( 'pxeboot', constants.NETWORK_TYPE_PXEBOOT, + constants.INTERFACE_CLASS_PLATFORM, providernetworks='group0-data0', expect_errors=True) # Expected message: Name must be unique def test_create_invalid_ae_name(self): self._create_ethernet('enp0s9', constants.NETWORK_TYPE_NONE) self._create_bond('enp0s9', constants.NETWORK_TYPE_MGMT, + constants.INTERFACE_CLASS_PLATFORM, expect_errors=True) # Expected message: @@ -1416,40 +1595,32 @@ class TestPost(InterfaceTestCase): # interface def test_create_invalid_oam_data_ethernet(self): self._create_ethernet('shared', - networktype=(constants.NETWORK_TYPE_OAM + ',' + - constants.NETWORK_TYPE_DATA), - expect_errors=True) + networktype=[constants.NETWORK_TYPE_OAM, + constants.NETWORK_TYPE_DATA], + expect_errors=True) # Expected message: # Only pxeboot,mgmt,infra network types can be combined on a single # interface def test_create_invalid_mgmt_data_ethernet(self): self._create_ethernet('shared', - networktype=(constants.NETWORK_TYPE_MGMT + ',' + - constants.NETWORK_TYPE_DATA), - providernetworks='group0-data0', - host=self.compute, - expect_errors=True) + networktype=[constants.NETWORK_TYPE_MGMT, + constants.NETWORK_TYPE_DATA], + providernetworks='group0-data0', + host=self.compute, + expect_errors=True) # Expected message: # Only pxeboot,mgmt,infra network types can be combined on a single # interface def test_create_invalid_pxeboot_data_ethernet(self): self._create_ethernet('shared', - networktype=(constants.NETWORK_TYPE_DATA + ',' + - constants.NETWORK_TYPE_PXEBOOT), + networktype=[constants.NETWORK_TYPE_DATA, + constants.NETWORK_TYPE_PXEBOOT], providernetworks='group0-data0', host=self.compute, expect_errors=True) - # Expected message: - # Cannot determine primary network type of interface ___ from mgmt,infra - def test_create_invalid_mgmt_infra_ethernet(self): - self._create_ethernet('shared', - networktype=(constants.NETWORK_TYPE_MGMT + ',' + - constants.NETWORK_TYPE_INFRA), - expect_errors=True) - class TestCpePost(InterfaceTestCase): def setUp(self): @@ -1461,26 +1632,28 @@ class TestCpePost(InterfaceTestCase): # Network type list may only contain at most one type def test_create_ae_with_networktypes(self): self._create_bond('bond0', - networktype=(constants.NETWORK_TYPE_DATA + ',' + - constants.NETWORK_TYPE_PXEBOOT), + networktype=[constants.NETWORK_TYPE_DATA, + constants.NETWORK_TYPE_PXEBOOT], providernetworks='group0-data0', expect_errors=True) # Expected message: # Network type list may only contain at most one type def test_create_invalid_infra_data_ae(self): self._create_bond('shared', - networktype=(constants.NETWORK_TYPE_INFRA + ',' + - constants.NETWORK_TYPE_DATA), - providernetworks='group0-data0', - expect_errors=True) + networktype=[constants.NETWORK_TYPE_INFRA, + constants.NETWORK_TYPE_DATA], + providernetworks='group0-data0', + expect_errors=True) # Expected message: oam VLAN cannot be created over an interface with # network type data def test_create_oam_vlan_over_data_lag(self): bond_iface = self._create_bond( - 'data', constants.NETWORK_TYPE_DATA, providernetworks='group0-ext1') + 'data', constants.NETWORK_TYPE_DATA, + constants.INTERFACE_CLASS_DATA, providernetworks='group0-ext1') self._create_vlan( - 'oam', constants.NETWORK_TYPE_OAM, 2, + 'oam', constants.NETWORK_TYPE_OAM, + constants.INTERFACE_CLASS_PLATFORM, 2, lower_iface=bond_iface, providernetworks='group0-ext1', expect_errors=True) @@ -1488,9 +1661,11 @@ class TestCpePost(InterfaceTestCase): # network type data def test_create_infra_vlan_over_data_lag(self): bond_iface = self._create_bond( - 'data', constants.NETWORK_TYPE_DATA, providernetworks='group0-ext1') + 'data', constants.NETWORK_TYPE_DATA, + constants.INTERFACE_CLASS_DATA, providernetworks='group0-ext1') self._create_vlan( - 'infra', constants.NETWORK_TYPE_INFRA, 2, + 'infra', constants.NETWORK_TYPE_INFRA, + constants.INTERFACE_CLASS_PLATFORM, 2, lower_iface=bond_iface, providernetworks='group0-ext1', expect_errors=True) @@ -1498,9 +1673,11 @@ class TestCpePost(InterfaceTestCase): # network type data def test_create_mgmt_vlan_over_data_ethernet(self): port, iface = self._create_ethernet( - 'data', constants.NETWORK_TYPE_DATA, providernetworks='group0-ext1') + 'data', constants.NETWORK_TYPE_DATA, + constants.INTERFACE_CLASS_DATA, providernetworks='group0-ext1') self._create_vlan( - 'mgmt', constants.NETWORK_TYPE_MGMT, 2, + 'mgmt', constants.NETWORK_TYPE_MGMT, + constants.INTERFACE_CLASS_PLATFORM, 2, lower_iface=iface, providernetworks='group0-ext1', expect_errors=True) @@ -1514,9 +1691,11 @@ class TestCpePost(InterfaceTestCase): # Expected message: VLAN id ___ already in use on interface ___ def test_create_vlan_id_already_in_use(self): port, iface = self._create_ethernet('eth1', constants.NETWORK_TYPE_NONE) - self._create_vlan('vlan1', constants.NETWORK_TYPE_DATA, 1, + self._create_vlan('vlan1', constants.NETWORK_TYPE_DATA, + constants.INTERFACE_CLASS_DATA, vlan_id=1, lower_iface=iface, providernetworks='group0-ext0') - self._create_vlan('vlan2', constants.NETWORK_TYPE_DATA, 1, + self._create_vlan('vlan2', constants.NETWORK_TYPE_DATA, + constants.INTERFACE_CLASS_DATA, vlan_id=1, lower_iface=iface, providernetworks='group0-ext1', expect_errors=True) @@ -1524,14 +1703,16 @@ class TestCpePost(InterfaceTestCase): def test_create_invalid_vlan_multiple_networktype(self): port, lower = self._create_ethernet('eth1', constants.NETWORK_TYPE_NONE) self._create_vlan('vlan2', - networktype=(constants.NETWORK_TYPE_MGMT + ',' + - constants.NETWORK_TYPE_DATA), + networktype=[constants.NETWORK_TYPE_MGMT, + constants.NETWORK_TYPE_DATA], + ifclass=constants.INTERFACE_CLASS_PLATFORM, vlan_id=2, lower_iface=lower, expect_errors=True) # Expected message: VLAN interfaces cannot have a network type of 'none' def test_create_invalid_vlan_networktype_none(self): port, lower = self._create_ethernet('eth1', constants.NETWORK_TYPE_NONE) self._create_vlan('vlan2', networktype='none', + ifclass=constants.INTERFACE_CLASS_NONE, vlan_id=2, lower_iface=lower, expect_errors=True) # Expected error: VLAN based provider network group0-data0 cannot be @@ -1539,6 +1720,7 @@ class TestCpePost(InterfaceTestCase): def test_create_invalid_vlan_with_vlan_provider_network(self): port, lower = self._create_ethernet('eth1', constants.NETWORK_TYPE_NONE) self._create_vlan('vlan2', networktype=constants.NETWORK_TYPE_DATA, + ifclass=constants.INTERFACE_CLASS_DATA, providernetworks='group0-data0', vlan_id=2, lower_iface=lower, expect_errors=True) @@ -1558,6 +1740,7 @@ class TestCpePost(InterfaceTestCase): providernetworks='group0-ext1', ifname='data1', networktype=constants.NETWORK_TYPE_DATA, + ifclass=constants.INTERFACE_CLASS_DATA, iftype=constants.INTERFACE_TYPE_ETHERNET, uses=['enp0s9']) self._post_and_check_failure(ndict) @@ -1577,9 +1760,11 @@ class TestCpePost(InterfaceTestCase): def test_create_invalid_provider_network_used(self): self._create_ethernet('data0', networktype=constants.NETWORK_TYPE_DATA, + ifclass=constants.INTERFACE_CLASS_DATA, providernetworks='group0-data0') self._create_ethernet('data1', networktype=constants.NETWORK_TYPE_DATA, + ifclass=constants.INTERFACE_CLASS_DATA, providernetworks='group0-data0', expect_errors=True) @@ -1587,6 +1772,7 @@ class TestCpePost(InterfaceTestCase): def test_create_invalid_provider_network_not_exist(self): self._create_ethernet('data0', networktype=constants.NETWORK_TYPE_DATA, + ifclass=constants.INTERFACE_CLASS_DATA, providernetworks='group0-dataXX', expect_errors=True) @@ -1595,6 +1781,7 @@ class TestCpePost(InterfaceTestCase): def test_create_invalid_duplicate_provider_network(self): self._create_ethernet('data0', networktype=constants.NETWORK_TYPE_DATA, + ifclass=constants.INTERFACE_CLASS_DATA, providernetworks='group0-data1,group0-data1', expect_errors=True) @@ -1605,6 +1792,7 @@ class TestCpePost(InterfaceTestCase): mock_providernet_extension_supported.return_value = False self._create_ethernet('data0', networktype=constants.NETWORK_TYPE_DATA, + ifclass=constants.INTERFACE_CLASS_DATA, providernetworks='group0-data1', expect_errors=True) @@ -1617,8 +1805,8 @@ class TestCpePatch(InterfaceTestCase): def test_create_invalid_infra_data_ethernet(self): self._create_ethernet('shared', - networktype=(constants.NETWORK_TYPE_INFRA + ',' + - constants.NETWORK_TYPE_DATA), + networktype=[constants.NETWORK_TYPE_INFRA, + constants.NETWORK_TYPE_DATA], providernetworks='group0-data0', expect_errors=True) @@ -1626,6 +1814,7 @@ class TestCpePatch(InterfaceTestCase): def test_patch_neutron_bind_failed(self, mock_neutron_bind_interface): port, interface = self._create_ethernet( 'data0', networktype=constants.NETWORK_TYPE_DATA, + ifclass=constants.INTERFACE_CLASS_DATA, providernetworks='group0-data0') mock_neutron_bind_interface.side_effect = [ @@ -1647,7 +1836,9 @@ class TestCpePatch(InterfaceTestCase): constants.NETWORK_TYPE_NONE) response = self.patch_dict_json( '%s' % self._get_path(interface['uuid']), - networktype=constants.NETWORK_TYPE_PCI_SRIOV, expect_errors=True) + networktype=constants.NETWORK_TYPE_PCI_SRIOV, + ifclass=constants.INTERFACE_CLASS_PCI_SRIOV, + expect_errors=True) self.assertEqual(http_client.BAD_REQUEST, response.status_int) self.assertEqual('application/json', response.content_type) @@ -1656,7 +1847,9 @@ class TestCpePatch(InterfaceTestCase): interface = dbutils.create_test_interface(forihostid='1') response = self.patch_dict_json( '%s' % self._get_path(interface['uuid']), sriov_numvfs=1, - networktype=constants.NETWORK_TYPE_PCI_SRIOV, expect_errors=True) + networktype=constants.NETWORK_TYPE_PCI_SRIOV, + ifclass=constants.INTERFACE_CLASS_DATA, + expect_errors=True) self.assertEqual(http_client.BAD_REQUEST, response.status_int) self.assertEqual('application/json', response.content_type) @@ -1668,7 +1861,9 @@ class TestCpePatch(InterfaceTestCase): pciaddr='0000:00:00.11', dev_id=0, sriov_totalvfs=0, sriov_numvfs=1) response = self.patch_dict_json( '%s' % self._get_path(interface['uuid']), - networktype=constants.NETWORK_TYPE_PCI_SRIOV, sriov_numvfs=1, + networktype=constants.NETWORK_TYPE_PCI_SRIOV, + ifclass=constants.INTERFACE_CLASS_PCI_SRIOV, + sriov_numvfs=1, expect_errors=True) self.assertEqual(http_client.BAD_REQUEST, response.status_int) self.assertEqual('application/json', response.content_type) @@ -1682,7 +1877,9 @@ class TestCpePatch(InterfaceTestCase): driver=None) response = self.patch_dict_json( '%s' % self._get_path(interface['uuid']), - networktype=constants.NETWORK_TYPE_PCI_SRIOV, sriov_numvfs=2, + networktype=constants.NETWORK_TYPE_PCI_SRIOV, + ifclass=constants.INTERFACE_CLASS_PCI_SRIOV, + sriov_numvfs=2, expect_errors=True) self.assertEqual(http_client.BAD_REQUEST, response.status_int) self.assertEqual('application/json', response.content_type) @@ -1696,7 +1893,9 @@ class TestCpePatch(InterfaceTestCase): driver=None) response = self.patch_dict_json( '%s' % self._get_path(interface['uuid']), - networktype=constants.NETWORK_TYPE_PCI_SRIOV, sriov_numvfs=1, + networktype=constants.NETWORK_TYPE_PCI_SRIOV, + ifclass=constants.INTERFACE_CLASS_PCI_SRIOV, + sriov_numvfs=1, expect_errors=True) self.assertEqual(http_client.BAD_REQUEST, response.status_int) self.assertEqual('application/json', response.content_type) diff --git a/sysinv/sysinv/sysinv/sysinv/tests/db/utils.py b/sysinv/sysinv/sysinv/sysinv/tests/db/utils.py index 28c6da7112..02dfa40c64 100644 --- a/sysinv/sysinv/sysinv/sysinv/tests/db/utils.py +++ b/sysinv/sysinv/sysinv/sysinv/tests/db/utils.py @@ -327,10 +327,7 @@ def get_test_network(**kw): 'id': kw.get('id'), 'uuid': kw.get('uuid'), 'type': kw.get('type'), - 'mtu': kw.get('mtu', 1500), - 'link_capacity': kw.get('link_capacity'), 'dynamic': kw.get('dynamic', True), - 'vlan_id': kw.get('vlan_id'), 'address_pool_id': kw.get('address_pool_id', None) } return inv @@ -617,7 +614,9 @@ def post_get_test_interface(**kw): 'iftype': kw.get('iftype', 'ethernet'), 'imac': kw.get('imac', '11:22:33:44:55:66'), 'imtu': kw.get('imtu', 1500), + 'ifclass': kw.get("ifclass"), 'networktype': kw.get('networktype'), + 'networks': kw.get('networks', []), 'aemode': kw.get('aemode', 'balanced'), 'txhashpolicy': kw.get('txhashpolicy', 'layer2'), 'providernetworks': kw.get('providernetworks'), @@ -643,7 +642,9 @@ def get_test_interface(**kw): 'iftype': kw.get('iftype', 'ethernet'), 'imac': kw.get('imac', '11:22:33:44:55:66'), 'imtu': kw.get('imtu', 1500), + 'ifclass': kw.get('ifclass', 'none'), 'networktype': kw.get('networktype'), + 'networks': kw.get('networks', []), 'aemode': kw.get('aemode'), 'txhashpolicy': kw.get('txhashpolicy', None), 'providernetworks': kw.get('providernetworks'), @@ -674,6 +675,30 @@ def create_test_interface(**kw): return dbapi.iinterface_create(forihostid, interface) +def create_test_interface_network(**kw): + """Create test network interface entry in DB and return Network DB + object. Function to be used to create test Network objects in the database. + :param kw: kwargs with overriding values for network's attributes. + :returns: Test Network DB object. + """ + network_interface = get_test_interface_network(**kw) + if 'id' not in kw: + del network_interface['id'] + dbapi = db_api.get_instance() + return dbapi.network_interface_create(network_interface) + + +def get_test_interface_network(**kw): + inv = { + 'id': kw.get('id'), + 'uuid': kw.get('uuid'), + 'forihostid': kw.get('forihostid'), + 'interface_id': kw.get('interface_id'), + 'network_id': kw.get('network_id'), + } + return inv + + def get_test_storage_tier(**kw): tier = { 'id': kw.get('id', 321), diff --git a/sysinv/sysinv/sysinv/sysinv/tests/puppet/test_interface.py b/sysinv/sysinv/sysinv/sysinv/tests/puppet/test_interface.py index 44197932d6..68749a33fc 100644 --- a/sysinv/sysinv/sysinv/sysinv/tests/puppet/test_interface.py +++ b/sysinv/sysinv/sysinv/sysinv/tests/puppet/test_interface.py @@ -21,17 +21,21 @@ from sysinv.tests.db import utils as dbutils NETWORKTYPES_WITH_V4_ADDRESSES = [constants.NETWORK_TYPE_MGMT, - constants.NETWORK_TYPE_DATA_VRS, constants.NETWORK_TYPE_OAM, constants.NETWORK_TYPE_PXEBOOT] NETWORKTYPES_WITH_V6_ADDRESSES = [constants.NETWORK_TYPE_INFRA, constants.NETWORK_TYPE_DATA] -NETWORKTYPES_WITH_V4_ROUTES = [constants.NETWORK_TYPE_DATA_VRS] +NETWORKTYPES_WITH_V4_ROUTES = [constants.NETWORK_TYPE_DATA] NETWORKTYPES_WITH_V6_ROUTES = [constants.NETWORK_TYPE_DATA] +PLATFORM_INTERFACE_CLASSES = [constants.NETWORK_TYPE_PXEBOOT, + constants.NETWORK_TYPE_MGMT, + constants.NETWORK_TYPE_INFRA, + constants.NETWORK_TYPE_OAM] + class BaseTestCase(dbbase.DbTestCase): @@ -107,12 +111,25 @@ class BaseTestCase(dbbase.DbTestCase): 'metric': '1'} self.routes.append(dbutils.create_test_route(**route)) - def _create_ethernet_test(self, ifname=None, networktype=None, **kwargs): - if isinstance(networktype, list): + def _create_ethernet_test(self, ifname=None, ifclass=None, + networktype=None, **kwargs): + if not isinstance(networktype, list): + networktypelist = [networktype] + else: + networktypelist = networktype networktype = ','.join(networktype) interface_id = len(self.interfaces) + networks = [] if not ifname: ifname = (networktype or 'eth') + str(interface_id) + if all(network_type in constants.PLATFORM_NETWORK_TYPES + for network_type in networktypelist): + ifclass = constants.INTERFACE_CLASS_PLATFORM + for network_type in networktypelist: + network = self.dbapi.network_get_by_type(network_type) + networks.append(str(network.id)) + if not ifclass and networktype: + ifclass = networktype interface = {'id': interface_id, 'uuid': str(uuid.uuid4()), 'forihostid': self.host.id, @@ -121,6 +138,8 @@ class BaseTestCase(dbbase.DbTestCase): '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)} @@ -144,14 +163,26 @@ class BaseTestCase(dbbase.DbTestCase): self._setup_address_and_routes(db_interface) return db_port, db_interface - def _create_vlan_test(self, ifname, networktype, vlan_id, + def _create_vlan_test(self, ifname, ifclass, networktype, vlan_id, lower_iface=None): - if isinstance(networktype, list): + if not isinstance(networktype, list): + networktypelist = [networktype] + else: + networktypelist = networktype networktype = ','.join(networktype) if not lower_iface: lower_port, lower_iface = self._create_ethernet_test() if not ifname: ifname = 'vlan' + str(vlan_id) + networks = [] + if all(network_type in constants.PLATFORM_NETWORK_TYPES + for network_type in networktypelist): + ifclass = constants.INTERFACE_CLASS_PLATFORM + for network_type in networktypelist: + network = self.dbapi.network_get_by_type(network_type) + networks.append(str(network.id)) + if not ifclass and networktype: + ifclass = networktype interface_id = len(self.interfaces) interface = {'id': interface_id, 'uuid': str(uuid.uuid4()), @@ -162,6 +193,8 @@ class BaseTestCase(dbbase.DbTestCase): 'imac': '02:11:22:33:44:' + str(10 + interface_id), 'uses': [lower_iface['ifname']], 'used_by': [], + 'ifclass': ifclass, + 'networks': networks, 'networktype': networktype, 'imtu': 1500} lower_iface['used_by'].append(interface['ifname']) @@ -170,14 +203,28 @@ class BaseTestCase(dbbase.DbTestCase): self._setup_address_and_routes(db_interface) return db_interface - def _create_bond_test(self, ifname, networktype=None): - if isinstance(networktype, list): + def _create_bond_test(self, ifname, ifclass=None, networktype=None): + if not isinstance(networktype, list): + networktypelist = [networktype] + else: + networktypelist = networktype networktype = ','.join(networktype) port1, iface1 = self._create_ethernet_test() port2, iface2 = self._create_ethernet_test() interface_id = len(self.interfaces) if not ifname: ifname = 'bond' + str(interface_id) + + networks = [] + if all(network_type in constants.PLATFORM_NETWORK_TYPES + for network_type in networktypelist): + ifclass = constants.INTERFACE_CLASS_PLATFORM + for network_type in networktypelist: + network = self.dbapi.network_get_by_type(network_type) + networks.append(str(network.id)) + if not ifclass and networktype: + ifclass = networktype + interface = {'id': interface_id, 'uuid': str(uuid.uuid4()), 'forihostid': self.host.id, @@ -186,6 +233,8 @@ class BaseTestCase(dbbase.DbTestCase): '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'} @@ -217,12 +266,6 @@ class BaseTestCase(dbbase.DbTestCase): ranges=[['192.168.202.2', '192.168.202.254']], prefix=24) - bm_pool = dbutils.create_test_address_pool( - network='192.168.203.0', - name='board-management', - ranges=[['192.168.203.2', '192.168.203.254']], - prefix=24) - infra_pool = dbutils.create_test_address_pool( network='192.168.205.0', name='infrastructure', @@ -237,7 +280,7 @@ class BaseTestCase(dbbase.DbTestCase): self.networks.append(dbutils.create_test_network( type=constants.NETWORK_TYPE_MGMT, - link_capacity=constants.LINK_SPEED_1G, + link_capacity=constants.LINK_SPEED_10G, vlan_id=2, address_pool_id=mgmt_pool.id)) @@ -247,12 +290,6 @@ class BaseTestCase(dbbase.DbTestCase): vlan_id=None, address_pool_id=pxeboot_pool.id)) - self.networks.append(dbutils.create_test_network( - type=constants.NETWORK_TYPE_BM, - link_capacity=constants.LINK_SPEED_1G, - vlan_id=78, - address_pool_id=bm_pool.id)) - self.networks.append(dbutils.create_test_network( type=constants.NETWORK_TYPE_INFRA, link_capacity=constants.LINK_SPEED_10G, @@ -306,26 +343,6 @@ class BaseTestCase(dbbase.DbTestCase): } dbutils.create_test_address(**address) - name = utils.format_address_name(constants.CONTROLLER_0_HOSTNAME, - constants.NETWORK_TYPE_BM) - address = { - 'name': name, - 'family': 4, - 'prefix': 24, - 'address': '192.168.203.3' - } - dbutils.create_test_address(**address) - - name = utils.format_address_name(constants.CONTROLLER_1_HOSTNAME, - constants.NETWORK_TYPE_BM) - address = { - 'name': name, - 'family': 4, - 'prefix': 24, - 'address': '192.168.203.4' - } - dbutils.create_test_address(**address) - def _create_test_floating_ips(self): name = utils.format_address_name(constants.CONTROLLER_HOSTNAME, constants.NETWORK_TYPE_MGMT) @@ -417,7 +434,7 @@ class InterfaceTestCase(BaseTestCase): self._create_test_common() self._create_test_host(constants.CONTROLLER) self.port, self.iface = self._create_ethernet_test( - "mgmt0", constants.NETWORK_TYPE_MGMT) + "mgmt0", None, constants.NETWORK_TYPE_MGMT) def _update_context(self): # ensure DB entries are updated prior to updating the context which @@ -432,11 +449,13 @@ class InterfaceTestCase(BaseTestCase): self._setup_context() def test_is_platform_network_type_true(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_PLATFORM self.iface['networktype'] = constants.NETWORK_TYPE_MGMT result = interface.is_platform_network_type(self.iface) self.assertTrue(result) def test_is_platform_network_type_false(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_DATA self.iface['networktype'] = constants.NETWORK_TYPE_DATA result = interface.is_platform_network_type(self.iface) self.assertFalse(result) @@ -510,10 +529,12 @@ class InterfaceTestCase(BaseTestCase): self.assertFalse(interface.is_compute_subfunction(self.context)) def test_is_pci_interface_true(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_PCI_SRIOV self.iface['networktype'] = constants.NETWORK_TYPE_PCI_SRIOV self.assertTrue(interface.is_pci_interface(self.iface)) def test_is_pci_interface_false(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_DATA self.iface['networktype'] = constants.NETWORK_TYPE_DATA self.assertFalse(interface.is_pci_interface(self.iface)) @@ -531,7 +552,8 @@ class InterfaceTestCase(BaseTestCase): def test_get_lower_interface(self): vlan = self._create_vlan_test( - "infra", constants.NETWORK_TYPE_INFRA, 1, self.iface) + "infra", constants.INTERFACE_CLASS_PLATFORM, + constants.NETWORK_TYPE_INFRA, 1, self.iface) self._update_context() value = interface.get_lower_interface(self.context, vlan) self.assertEqual(value, self.iface) @@ -547,7 +569,8 @@ class InterfaceTestCase(BaseTestCase): def test_get_interface_os_ifname_vlan_over_ethernet(self): vlan = self._create_vlan_test( - "infra", constants.NETWORK_TYPE_INFRA, 1, self.iface) + "infra", constants.INTERFACE_CLASS_PLATFORM, + constants.NETWORK_TYPE_INFRA, 1, self.iface) self._update_context() value = interface.get_interface_os_ifname(self.context, vlan) self.assertEqual(value, self.port['name'] + ".1") @@ -555,7 +578,8 @@ class InterfaceTestCase(BaseTestCase): def test_get_interface_os_ifname_vlan_over_bond(self): bond = self._create_bond_test("none") vlan = self._create_vlan_test( - "infra", constants.NETWORK_TYPE_INFRA, 1, bond) + "infra", constants.INTERFACE_CLASS_PLATFORM, + constants.NETWORK_TYPE_INFRA, 1, bond) self._update_context() value = interface.get_interface_os_ifname(self.context, vlan) self.assertEqual(value, bond['ifname'] + ".1") @@ -596,56 +620,58 @@ class InterfaceTestCase(BaseTestCase): self.assertEqual(family, 'inet') def test_get_interface_gateway_address_oam(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_PLATFORM self.iface['networktype'] = constants.NETWORK_TYPE_OAM gateway = interface.get_interface_gateway_address( - self.context, self.iface) + self.context, constants.NETWORK_TYPE_OAM) expected = str(self.oam_gateway_address.ip) self.assertEqual(gateway, expected) def test_get_interface_gateway_address_mgmt(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_PLATFORM self.iface['networktype'] = constants.NETWORK_TYPE_MGMT gateway = interface.get_interface_gateway_address( - self.context, self.iface) + self.context, constants.NETWORK_TYPE_MGMT) expected = str(self.mgmt_gateway_address.ip) self.assertEqual(gateway, expected) def test_get_interface_gateway_address_none(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_DATA self.iface['networktype'] = constants.NETWORK_TYPE_DATA gateway = interface.get_interface_gateway_address( - self.context, self.iface) + self.context, constants.NETWORK_TYPE_DATA) self.assertIsNone(gateway) def test_get_interface_address_method_for_none(self): + self.iface['ifclass'] = None self.iface['networktype'] = None method = interface.get_interface_address_method( self.context, self.iface) self.assertEqual(method, 'manual') def test_get_interface_address_method_for_data(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_DATA self.iface['networktype'] = constants.NETWORK_TYPE_DATA method = interface.get_interface_address_method( self.context, self.iface) self.assertEqual(method, 'manual') - def test_get_interface_address_method_for_data_vrs(self): - self.iface['networktype'] = constants.NETWORK_TYPE_DATA_VRS - method = interface.get_interface_address_method( - self.context, self.iface) - self.assertEqual(method, 'static') - def test_get_interface_address_method_for_pci_sriov(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_PCI_SRIOV self.iface['networktype'] = constants.NETWORK_TYPE_PCI_SRIOV 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.iface['ifclass'] = constants.INTERFACE_CLASS_PCI_PASSTHROUGH self.iface['networktype'] = constants.NETWORK_TYPE_PCI_PASSTHROUGH method = interface.get_interface_address_method( self.context, self.iface) self.assertEqual(method, 'manual') def test_get_interface_address_method_for_pxeboot_compute(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_PLATFORM self.iface['networktype'] = constants.NETWORK_TYPE_PXEBOOT self.host['personality'] = constants.COMPUTE self._update_context() @@ -654,6 +680,7 @@ class InterfaceTestCase(BaseTestCase): self.assertEqual(method, 'manual') def test_get_interface_address_method_for_pxeboot_storage(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_PLATFORM self.iface['networktype'] = constants.NETWORK_TYPE_PXEBOOT self.host['personality'] = constants.STORAGE self._update_context() @@ -662,6 +689,7 @@ class InterfaceTestCase(BaseTestCase): self.assertEqual(method, 'manual') def test_get_interface_address_method_for_pxeboot_controller(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_PLATFORM self.iface['networktype'] = constants.NETWORK_TYPE_PXEBOOT self.host['personality'] = constants.CONTROLLER self._update_context() @@ -670,6 +698,7 @@ class InterfaceTestCase(BaseTestCase): self.assertEqual(method, 'static') def test_get_interface_address_method_for_mgmt_compute(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_PLATFORM self.iface['networktype'] = constants.NETWORK_TYPE_MGMT self.host['personality'] = constants.COMPUTE self._update_context() @@ -678,6 +707,7 @@ class InterfaceTestCase(BaseTestCase): self.assertEqual(method, 'dhcp') def test_get_interface_address_method_for_mgmt_storage(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_PLATFORM self.iface['networktype'] = constants.NETWORK_TYPE_MGMT self.host['personality'] = constants.STORAGE self._update_context() @@ -686,6 +716,7 @@ class InterfaceTestCase(BaseTestCase): self.assertEqual(method, 'dhcp') def test_get_interface_address_method_for_mgmt_controller(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_PLATFORM self.iface['networktype'] = constants.NETWORK_TYPE_MGMT self.host['personality'] = constants.CONTROLLER self._update_context() @@ -694,6 +725,7 @@ class InterfaceTestCase(BaseTestCase): self.assertEqual(method, 'static') def test_get_interface_address_method_for_infra_compute(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_PLATFORM self.iface['networktype'] = constants.NETWORK_TYPE_INFRA self.host['personality'] = constants.COMPUTE self._update_context() @@ -702,6 +734,7 @@ class InterfaceTestCase(BaseTestCase): self.assertEqual(method, 'dhcp') def test_get_interface_address_method_for_infra_storage(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_PLATFORM self.iface['networktype'] = constants.NETWORK_TYPE_INFRA self.host['personality'] = constants.STORAGE self._update_context() @@ -710,6 +743,7 @@ class InterfaceTestCase(BaseTestCase): self.assertEqual(method, 'dhcp') def test_get_interface_address_method_for_infra_controller(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_PLATFORM self.iface['networktype'] = constants.NETWORK_TYPE_INFRA self.host['personality'] = constants.CONTROLLER self._update_context() @@ -718,6 +752,7 @@ class InterfaceTestCase(BaseTestCase): self.assertEqual(method, 'static') def test_get_interface_address_method_for_oam_controller(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_PLATFORM self.iface['networktype'] = constants.NETWORK_TYPE_OAM self.host['personality'] = constants.CONTROLLER self._update_context() @@ -726,18 +761,28 @@ class InterfaceTestCase(BaseTestCase): self.assertEqual(method, 'static') def test_get_interface_traffic_classifier_for_mgmt(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_PLATFORM self.iface['networktype'] = constants.NETWORK_TYPE_MGMT + for network in self.networks: + if network['type'] == constants.NETWORK_TYPE_MGMT: + net_id = network['id'] + self.iface['networks'] = [str(net_id)] classifier = interface.get_interface_traffic_classifier( self.context, self.iface) print(self.context) expected = ('/usr/local/bin/cgcs_tc_setup.sh %s %s %s > /dev/null' % (self.port['name'], constants.NETWORK_TYPE_MGMT, - constants.LINK_SPEED_1G)) + constants.LINK_SPEED_10G)) self.assertEqual(classifier, expected) def test_get_interface_traffic_classifier_for_infra(self): self.iface['ifname'] = 'infra0' + self.iface['ifclass'] = constants.INTERFACE_CLASS_PLATFORM self.iface['networktype'] = constants.NETWORK_TYPE_INFRA + for network in self.networks: + if network['type'] == constants.NETWORK_TYPE_INFRA: + net_id = network['id'] + self.iface['networks'] = [str(net_id)] classifier = interface.get_interface_traffic_classifier( self.context, self.iface) expected = ('/usr/local/bin/cgcs_tc_setup.sh %s %s %s > /dev/null' % @@ -746,7 +791,12 @@ class InterfaceTestCase(BaseTestCase): self.assertEqual(classifier, expected) def test_get_interface_traffic_classifier_for_oam(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_PLATFORM self.iface['networktype'] = constants.NETWORK_TYPE_OAM + for network in self.networks: + if network['type'] == constants.NETWORK_TYPE_OAM: + net_id = network['id'] + self.iface['networks'] = [str(net_id)] classifier = interface.get_interface_traffic_classifier( self.context, self.iface) self.assertIsNone(classifier) @@ -758,6 +808,7 @@ class InterfaceTestCase(BaseTestCase): self.assertIsNone(classifier) def test_get_bridge_interface_name_none_dpdk_supported(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_DATA self.iface['networktype'] = constants.NETWORK_TYPE_DATA self.port['dpdksupport'] = True self._update_context() @@ -765,11 +816,13 @@ class InterfaceTestCase(BaseTestCase): self.assertIsNone(ifname) def test_get_bridge_interface_name_none_not_data(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_PLATFORM self.iface['networktype'] = constants.NETWORK_TYPE_MGMT ifname = interface.get_bridge_interface_name(self.context, self.iface) self.assertIsNone(ifname) def test_get_bridge_interface_name(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_DATA self.iface['networktype'] = constants.NETWORK_TYPE_DATA self.port['dpdksupport'] = False self._update_context() @@ -777,6 +830,7 @@ class InterfaceTestCase(BaseTestCase): self.assertEqual(ifname, 'br-' + self.port['name']) def test_needs_interface_config_kernel_mgmt(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_PLATFORM self.iface['networktype'] = constants.NETWORK_TYPE_MGMT self.host['personality'] = constants.CONTROLLER self._update_context() @@ -784,6 +838,7 @@ class InterfaceTestCase(BaseTestCase): self.assertTrue(needed) def test_needs_interface_config_kernel_infra(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_PLATFORM self.iface['networktype'] = constants.NETWORK_TYPE_INFRA self.host['personality'] = constants.CONTROLLER self._update_context() @@ -791,20 +846,15 @@ class InterfaceTestCase(BaseTestCase): self.assertTrue(needed) def test_needs_interface_config_kernel_oam(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_PLATFORM self.iface['networktype'] = constants.NETWORK_TYPE_OAM self.host['personality'] = constants.CONTROLLER self._update_context() needed = interface.needs_interface_config(self.context, self.iface) self.assertTrue(needed) - def test_needs_interface_config_kernel_vrs(self): - self.iface['networktype'] = constants.NETWORK_TYPE_DATA_VRS - self.host['personality'] = constants.CONTROLLER - self._update_context() - needed = interface.needs_interface_config(self.context, self.iface) - self.assertTrue(needed) - def test_needs_interface_config_data(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_DATA self.iface['networktype'] = constants.NETWORK_TYPE_DATA self.host['personality'] = constants.CONTROLLER self.port['dpdksupport'] = True @@ -813,6 +863,7 @@ class InterfaceTestCase(BaseTestCase): self.assertFalse(needed) def test_needs_interface_config_data_slow(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_DATA self.iface['networktype'] = constants.NETWORK_TYPE_DATA self.host['personality'] = constants.CONTROLLER self.port['dpdksupport'] = False @@ -821,6 +872,7 @@ class InterfaceTestCase(BaseTestCase): self.assertFalse(needed) def test_needs_interface_config_data_mlx4(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_DATA self.iface['networktype'] = constants.NETWORK_TYPE_DATA self.host['personality'] = constants.CONTROLLER self.port['driver'] = interface.DRIVER_MLX_CX3 @@ -829,6 +881,7 @@ class InterfaceTestCase(BaseTestCase): self.assertFalse(needed) def test_needs_interface_config_data_mlx5(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_DATA self.iface['networktype'] = constants.NETWORK_TYPE_DATA self.host['personality'] = constants.CONTROLLER self.port['driver'] = interface.DRIVER_MLX_CX4 @@ -837,6 +890,7 @@ class InterfaceTestCase(BaseTestCase): self.assertFalse(needed) def test_needs_interface_config_data_slow_compute(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_DATA self.iface['networktype'] = constants.NETWORK_TYPE_DATA self.host['personality'] = constants.COMPUTE self.port['dpdksupport'] = False @@ -845,6 +899,7 @@ class InterfaceTestCase(BaseTestCase): self.assertTrue(needed) def test_needs_interface_config_data_mlx4_compute(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_DATA self.iface['networktype'] = constants.NETWORK_TYPE_DATA self.host['personality'] = constants.COMPUTE self.port['driver'] = interface.DRIVER_MLX_CX3 @@ -853,6 +908,7 @@ class InterfaceTestCase(BaseTestCase): self.assertTrue(needed) def test_needs_interface_config_data_mlx5_compute(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_DATA self.iface['networktype'] = constants.NETWORK_TYPE_DATA self.host['personality'] = constants.COMPUTE self.port['driver'] = interface.DRIVER_MLX_CX4 @@ -861,6 +917,7 @@ class InterfaceTestCase(BaseTestCase): self.assertTrue(needed) def test_needs_interface_config_sriov_compute(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_PCI_SRIOV self.iface['networktype'] = constants.NETWORK_TYPE_PCI_SRIOV self.host['personality'] = constants.COMPUTE self._update_context() @@ -868,6 +925,7 @@ class InterfaceTestCase(BaseTestCase): self.assertTrue(needed) def test_needs_interface_config_pthru_compute(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_PCI_PASSTHROUGH self.iface['networktype'] = constants.NETWORK_TYPE_PCI_PASSTHROUGH self.host['personality'] = constants.COMPUTE self._update_context() @@ -875,6 +933,7 @@ class InterfaceTestCase(BaseTestCase): self.assertTrue(needed) def test_needs_interface_config_data_cpe_compute(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_DATA self.iface['networktype'] = constants.NETWORK_TYPE_DATA self.host['personality'] = constants.CONTROLLER self.host['subfunctions'] = constants.COMPUTE @@ -884,6 +943,7 @@ class InterfaceTestCase(BaseTestCase): self.assertFalse(needed) def test_needs_interface_config_data_slow_cpe_compute(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_DATA self.iface['networktype'] = constants.NETWORK_TYPE_DATA self.host['personality'] = constants.CONTROLLER self.host['subfunctions'] = constants.COMPUTE @@ -893,6 +953,7 @@ class InterfaceTestCase(BaseTestCase): self.assertTrue(needed) def test_needs_interface_config_data_mlx4_cpe_compute(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_DATA self.iface['networktype'] = constants.NETWORK_TYPE_DATA self.host['personality'] = constants.CONTROLLER self.host['subfunctions'] = constants.COMPUTE @@ -902,6 +963,7 @@ class InterfaceTestCase(BaseTestCase): self.assertTrue(needed) def test_needs_interface_config_data_mlx5_cpe_compute(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_DATA self.iface['networktype'] = constants.NETWORK_TYPE_DATA self.host['personality'] = constants.CONTROLLER self.host['subfunctions'] = constants.COMPUTE @@ -911,6 +973,7 @@ class InterfaceTestCase(BaseTestCase): self.assertTrue(needed) def test_needs_interface_config_sriov_cpe(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_PCI_SRIOV self.iface['networktype'] = constants.NETWORK_TYPE_PCI_SRIOV self.host['personality'] = constants.CONTROLLER self.host['subfunctions'] = constants.CONTROLLER @@ -919,6 +982,7 @@ class InterfaceTestCase(BaseTestCase): self.assertFalse(needed) def test_needs_interface_config_sriov_cpe_compute(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_PCI_SRIOV self.iface['networktype'] = constants.NETWORK_TYPE_PCI_SRIOV self.host['personality'] = constants.CONTROLLER self.host['subfunctions'] = constants.COMPUTE @@ -927,6 +991,7 @@ class InterfaceTestCase(BaseTestCase): self.assertTrue(needed) def test_needs_interface_config_pthru_cpe_compute(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_PCI_PASSTHROUGH self.iface['networktype'] = constants.NETWORK_TYPE_PCI_PASSTHROUGH self.host['personality'] = constants.CONTROLLER self.host['subfunctions'] = constants.COMPUTE @@ -988,7 +1053,12 @@ class InterfaceTestCase(BaseTestCase): self.assertEqual(result, expected) def test_get_controller_ethernet_config_oam(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_PLATFORM self.iface['networktype'] = constants.NETWORK_TYPE_OAM + for network in self.networks: + if network['type'] == constants.NETWORK_TYPE_OAM: + net_id = network['id'] + self.iface['networks'] = [str(net_id)] self._update_context() config = interface.get_interface_network_config( self.context, self.iface) @@ -1000,7 +1070,12 @@ class InterfaceTestCase(BaseTestCase): self.assertEqual(expected, config) def test_get_controller_ethernet_config_mgmt(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_PLATFORM self.iface['networktype'] = constants.NETWORK_TYPE_MGMT + for network in self.networks: + if network['type'] == constants.NETWORK_TYPE_MGMT: + net_id = network['id'] + self.iface['networks'] = [str(net_id)] self._update_context() config = interface.get_interface_network_config( self.context, self.iface) @@ -1008,7 +1083,7 @@ class InterfaceTestCase(BaseTestCase): 'post_up': '/usr/local/bin/cgcs_tc_setup.sh %s %s %s > /dev/null' % (self.port['name'], constants.NETWORK_TYPE_MGMT, - constants.LINK_SPEED_1G)} + constants.LINK_SPEED_10G)} expected = self._get_static_network_config( ifname=self.port['name'], mtu=1500, gateway='192.168.204.1', options=options) @@ -1016,7 +1091,12 @@ class InterfaceTestCase(BaseTestCase): self.assertEqual(expected, config) def test_get_controller_ethernet_config_infra(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_PLATFORM self.iface['networktype'] = constants.NETWORK_TYPE_INFRA + for network in self.networks: + if network['type'] == constants.NETWORK_TYPE_INFRA: + net_id = network['id'] + self.iface['networks'] = [str(net_id)] self._update_context() config = interface.get_interface_network_config( self.context, self.iface) @@ -1088,7 +1168,7 @@ class InterfaceTestCase(BaseTestCase): self.assertEqual(expected, config) def test_get_controller_vlan_config(self): - vlan = self._create_vlan_test("vlan1", None, 1, self.iface) + vlan = self._create_vlan_test("vlan1", None, None, 1, self.iface) self._update_context() config = interface.get_interface_network_config(self.context, vlan) options = {'VLAN': 'yes', @@ -1101,7 +1181,7 @@ class InterfaceTestCase(BaseTestCase): def test_get_controller_vlan_config_over_bond(self): bond = self._create_bond_test("bond0") - vlan = self._create_vlan_test("vlan1", None, 1, bond) + vlan = self._create_vlan_test("vlan1", None, None, 1, bond) self._update_context() config = interface.get_interface_network_config(self.context, vlan) options = {'VLAN': 'yes', @@ -1113,8 +1193,13 @@ class InterfaceTestCase(BaseTestCase): self.assertEqual(expected, config) def test_get_compute_ethernet_config_mgmt(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_PLATFORM self.iface['networktype'] = constants.NETWORK_TYPE_MGMT self.host['personality'] = constants.COMPUTE + for network in self.networks: + if network['type'] == constants.NETWORK_TYPE_MGMT: + net_id = network['id'] + self.iface['networks'] = [str(net_id)] self._update_context() config = interface.get_interface_network_config( self.context, self.iface) @@ -1122,15 +1207,20 @@ class InterfaceTestCase(BaseTestCase): 'post_up': '/usr/local/bin/cgcs_tc_setup.sh %s %s %s > /dev/null' % (self.port['name'], constants.NETWORK_TYPE_MGMT, - constants.LINK_SPEED_1G)} + constants.LINK_SPEED_10G)} expected = self._get_network_config( ifname=self.port['name'], mtu=1500, options=options) print(expected) self.assertEqual(expected, config) def test_get_compute_ethernet_config_infra(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_PLATFORM self.iface['networktype'] = constants.NETWORK_TYPE_INFRA self.host['personality'] = constants.COMPUTE + for network in self.networks: + if network['type'] == constants.NETWORK_TYPE_INFRA: + net_id = network['id'] + self.iface['networks'] = [str(net_id)] self._update_context() config = interface.get_interface_network_config( self.context, self.iface) @@ -1145,6 +1235,7 @@ class InterfaceTestCase(BaseTestCase): self.assertEqual(expected, config) def test_get_compute_ethernet_config_pci_sriov(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_PCI_SRIOV self.iface['networktype'] = constants.NETWORK_TYPE_PCI_SRIOV self.host['personality'] = constants.COMPUTE self._update_context() @@ -1161,6 +1252,7 @@ class InterfaceTestCase(BaseTestCase): self.assertEqual(expected, config) def test_get_compute_ethernet_config_pci_pthru(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_PCI_PASSTHROUGH self.iface['networktype'] = constants.NETWORK_TYPE_PCI_PASSTHROUGH self.host['personality'] = constants.COMPUTE self._update_context() @@ -1176,19 +1268,8 @@ class InterfaceTestCase(BaseTestCase): print(expected) self.assertEqual(expected, config) - def test_get_compute_ethernet_config_data_vrs(self): - self.iface['networktype'] = constants.NETWORK_TYPE_DATA_VRS - self.host['personality'] = constants.COMPUTE - self._update_context() - config = interface.get_interface_network_config( - self.context, self.iface) - options = {'LINKDELAY': '20'} - expected = self._get_static_network_config( - ifname=self.port['name'], mtu=1500, options=options) - print(expected) - self.assertEqual(expected, config) - def test_get_compute_ethernet_config_data_slow(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_DATA self.iface['networktype'] = constants.NETWORK_TYPE_DATA self.port['dpdksupport'] = False self.host['personality'] = constants.COMPUTE @@ -1204,7 +1285,8 @@ class InterfaceTestCase(BaseTestCase): self.assertEqual(expected, config) def test_get_compute_ethernet_config_data_slow_as_bond_slave(self): - bond = self._create_bond_test("data1", constants.NETWORK_TYPE_DATA) + bond = self._create_bond_test("data1", constants.INTERFACE_CLASS_DATA, + constants.NETWORK_TYPE_DATA) self.host['personality'] = constants.COMPUTE self._update_context() lower_ifname = bond['uses'][0] @@ -1224,6 +1306,7 @@ class InterfaceTestCase(BaseTestCase): self.assertEqual(expected, config) def test_get_compute_ethernet_config_data_slow_bridge(self): + self.iface['ifclass'] = constants.INTERFACE_CLASS_DATA self.iface['networktype'] = constants.NETWORK_TYPE_DATA self.port['dpdksupport'] = False self.host['personality'] = constants.COMPUTE @@ -1362,7 +1445,8 @@ class InterfaceTestCase(BaseTestCase): def _create_sriov_cx3_if_test(self, name, vf_num, **kwargs): port, iface = self._create_ethernet_test( - name, constants.NETWORK_TYPE_PCI_SRIOV, + name, constants.INTERFACE_CLASS_PCI_SRIOV, + constants.NETWORK_TYPE_PCI_SRIOV, driver=interface.DRIVER_MLX_CX3, sriov_numvfs=vf_num, **kwargs) return port, iface @@ -1421,12 +1505,6 @@ class InterfaceHostTestCase(BaseTestCase): self.assertIn('routes', context) self.assertIn('gateways', context) - def test_find_bmc_lower_interface(self): - if self.expected_bmc_interface: - lower_iface = interface._find_bmc_lower_interface(self.context) - lower_ifname = lower_iface['ifname'] - self.assertEqual(lower_ifname, self.expected_bmc_interface) - def test_is_platform_interface(self): for iface in self.interfaces: expected = bool( @@ -1513,9 +1591,9 @@ class InterfaceControllerEthernet(InterfaceHostTestCase): # ethernet interfaces. self._create_test_common() self._create_test_host(constants.CONTROLLER) - self._create_ethernet_test('oam', constants.NETWORK_TYPE_OAM) - self._create_ethernet_test('mgmt', constants.NETWORK_TYPE_MGMT) - self._create_ethernet_test('infra', constants.NETWORK_TYPE_INFRA) + self._create_ethernet_test('oam', None, constants.NETWORK_TYPE_OAM) + self._create_ethernet_test('mgmt', None, constants.NETWORK_TYPE_MGMT) + self._create_ethernet_test('infra', None, constants.NETWORK_TYPE_INFRA) self._create_ethernet_test('none') def setUp(self): @@ -1530,9 +1608,9 @@ class InterfaceControllerBond(InterfaceHostTestCase): # aggregated ethernet interfaces. self._create_test_common() self._create_test_host(constants.CONTROLLER) - self._create_bond_test('oam', constants.NETWORK_TYPE_OAM) - self._create_bond_test('mgmt', constants.NETWORK_TYPE_MGMT) - self._create_bond_test('infra', constants.NETWORK_TYPE_INFRA) + self._create_bond_test('oam', None, constants.NETWORK_TYPE_OAM) + self._create_bond_test('mgmt', None, constants.NETWORK_TYPE_MGMT) + self._create_bond_test('infra', None, constants.NETWORK_TYPE_INFRA) def setUp(self): super(InterfaceControllerBond, self).setUp() @@ -1551,11 +1629,11 @@ class InterfaceControllerVlanOverBond(InterfaceHostTestCase): # vlan interfaces over aggregated ethernet interfaces self._create_test_common() self._create_test_host(constants.CONTROLLER) - bond = self._create_bond_test('pxeboot', + bond = self._create_bond_test('pxeboot', None, constants.NETWORK_TYPE_PXEBOOT) - self._create_vlan_test('oam', constants.NETWORK_TYPE_OAM, 1, bond) - self._create_vlan_test('mgmt', constants.NETWORK_TYPE_MGMT, 2, bond) - self._create_vlan_test('infra', constants.NETWORK_TYPE_INFRA, 3, + self._create_vlan_test('oam', None, constants.NETWORK_TYPE_OAM, 1, bond) + self._create_vlan_test('mgmt', None, constants.NETWORK_TYPE_MGMT, 2, bond) + self._create_vlan_test('infra', None, constants.NETWORK_TYPE_INFRA, 3, bond) self._create_ethernet_test('none') @@ -1574,11 +1652,11 @@ class InterfaceControllerVlanOverEthernet(InterfaceHostTestCase): self._create_test_common() self._create_test_host(constants.CONTROLLER) port, iface = self._create_ethernet_test( - 'pxeboot', constants.NETWORK_TYPE_PXEBOOT) - self._create_vlan_test('oam', constants.NETWORK_TYPE_OAM, 1, iface) - self._create_vlan_test('mgmt', constants.NETWORK_TYPE_MGMT, 2, + 'pxeboot', None, constants.NETWORK_TYPE_PXEBOOT) + self._create_vlan_test('oam', None, constants.NETWORK_TYPE_OAM, 1, iface) + self._create_vlan_test('mgmt', None, constants.NETWORK_TYPE_MGMT, 2, iface) - self._create_vlan_test('infra', constants.NETWORK_TYPE_INFRA, 3, + self._create_vlan_test('infra', None, constants.NETWORK_TYPE_INFRA, 3, iface) self._create_ethernet_test('none') @@ -1595,29 +1673,32 @@ class InterfaceComputeEthernet(InterfaceHostTestCase): # compute and all interfaces are ethernet interfaces. self._create_test_common() self._create_test_host(constants.COMPUTE) - self._create_ethernet_test('mgmt', constants.NETWORK_TYPE_MGMT) - self._create_ethernet_test('infra', constants.NETWORK_TYPE_INFRA) - self._create_ethernet_test('vrs', constants.NETWORK_TYPE_DATA_VRS) - self._create_ethernet_test('data', constants.NETWORK_TYPE_DATA) - self._create_ethernet_test('sriov', + self._create_ethernet_test('mgmt', None, constants.NETWORK_TYPE_MGMT) + self._create_ethernet_test('infra', None, constants.NETWORK_TYPE_INFRA) + 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', + self._create_ethernet_test('pthru', constants.INTERFACE_CLASS_PCI_PASSTHROUGH, constants.NETWORK_TYPE_PCI_PASSTHROUGH) port, iface = ( - self._create_ethernet_test('slow', constants.NETWORK_TYPE_DATA, + self._create_ethernet_test('slow', constants.INTERFACE_CLASS_DATA, + constants.NETWORK_TYPE_DATA, dpdksupport=False)) port, iface = ( - self._create_ethernet_test('mlx4', constants.NETWORK_TYPE_DATA, + self._create_ethernet_test('mlx4', constants.INTERFACE_CLASS_DATA, + constants.NETWORK_TYPE_DATA, driver=interface.DRIVER_MLX_CX3)) port, iface = ( - self._create_ethernet_test('mlx5', constants.NETWORK_TYPE_DATA, + self._create_ethernet_test('mlx5', constants.INTERFACE_CLASS_DATA, + constants.NETWORK_TYPE_DATA, driver=interface.DRIVER_MLX_CX4)) self._create_ethernet_test('none') def setUp(self): super(InterfaceComputeEthernet, self).setUp() self.expected_bmc_interface = 'mgmt' - self.expected_platform_interfaces = ['mgmt', 'infra', 'vrs'] + self.expected_platform_interfaces = ['mgmt', 'infra'] self.expected_data_interfaces = ['slow', 'data', 'mlx4', 'mlx5'] self.expected_pci_interfaces = ['sriov', 'pthru'] self.expected_slow_interfaces = ['slow'] @@ -1634,24 +1715,23 @@ class InterfaceComputeVlanOverEthernet(InterfaceHostTestCase): self._create_test_common() self._create_test_host(constants.COMPUTE) port, iface = self._create_ethernet_test( - 'pxeboot', constants.NETWORK_TYPE_PXEBOOT) - self._create_vlan_test('mgmt', constants.NETWORK_TYPE_MGMT, 2, + 'pxeboot', None, constants.NETWORK_TYPE_PXEBOOT) + self._create_vlan_test('mgmt', None, constants.NETWORK_TYPE_MGMT, 2, iface) - self._create_vlan_test('infra', constants.NETWORK_TYPE_INFRA, 3) - self._create_vlan_test('vrs', constants.NETWORK_TYPE_DATA_VRS, 4) - self._create_vlan_test('data', constants.NETWORK_TYPE_DATA, 5) - self._create_ethernet_test('sriov', + self._create_vlan_test('infra', None, constants.NETWORK_TYPE_INFRA, 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', + 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', 'infra', - 'eth4', 'vrs'] - self.expected_data_interfaces = ['eth6', 'data'] + 'eth2', 'infra'] + self.expected_data_interfaces = ['eth4', 'data'] self.expected_pci_interfaces = ['sriov', 'pthru'] @@ -1661,22 +1741,23 @@ class InterfaceComputeBond(InterfaceHostTestCase): self._create_test_common() # compute and all interfaces are aggregated ethernet interfaces. self._create_test_host(constants.COMPUTE) - self._create_bond_test('mgmt', constants.NETWORK_TYPE_MGMT) - self._create_bond_test('infra', constants.NETWORK_TYPE_INFRA) - self._create_bond_test('vrs', constants.NETWORK_TYPE_DATA_VRS) - self._create_bond_test('data', constants.NETWORK_TYPE_DATA) + self._create_bond_test('mgmt', None, constants.NETWORK_TYPE_MGMT) + self._create_bond_test('infra', None, constants.NETWORK_TYPE_INFRA) + 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(InterfaceComputeBond, self).setUp() self.expected_bmc_interface = 'mgmt' self.expected_platform_interfaces = ['eth0', 'eth1', 'mgmt', - 'eth3', 'eth4', 'infra', - 'eth6', 'eth7', 'vrs'] - self.expected_data_interfaces = ['eth9', 'eth10', 'data', + 'eth3', 'eth4', 'infra'] + self.expected_data_interfaces = ['eth6', 'eth7', 'data', 'eth12', 'eth13', 'ex'] self.expected_pci_interfaces = ['sriov', 'pthru'] self.expected_slave_interfaces = ['eth0', 'eth1', 'eth3', 'eth4', @@ -1691,29 +1772,28 @@ class InterfaceComputeVlanOverBond(InterfaceHostTestCase): # interfaces. self._create_test_common() self._create_test_host(constants.COMPUTE) - bond = self._create_bond_test('pxeboot', + bond = self._create_bond_test('pxeboot', None, constants.NETWORK_TYPE_PXEBOOT) - self._create_vlan_test('oam', constants.NETWORK_TYPE_OAM, 1, bond) - self._create_vlan_test('mgmt', constants.NETWORK_TYPE_MGMT, 2, bond) - self._create_vlan_test('infra', constants.NETWORK_TYPE_INFRA, 3, + self._create_vlan_test('oam', None, constants.NETWORK_TYPE_OAM, 1, bond) + self._create_vlan_test('mgmt', None, constants.NETWORK_TYPE_MGMT, 2, bond) + self._create_vlan_test('infra', None, constants.NETWORK_TYPE_INFRA, 3, bond) - bond1 = self._create_bond_test('bond1') - self._create_vlan_test('vrs', constants.NETWORK_TYPE_DATA_VRS, 4, - bond1) bond2 = self._create_bond_test('bond2') - self._create_vlan_test('data', constants.NETWORK_TYPE_DATA, 5, + 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', 'infra', - 'eth6', 'eth7', 'bond1', 'vrs'] - self.expected_data_interfaces = ['eth10', 'eth11', 'bond2', 'data', + 'oam', 'mgmt', 'infra'] + self.expected_data_interfaces = ['eth6', 'eth7', 'bond2', 'data', 'eth14', 'eth15'] self.expected_slave_interfaces = ['eth0', 'eth1', 'eth6', 'eth7', @@ -1721,37 +1801,6 @@ class InterfaceComputeVlanOverBond(InterfaceHostTestCase): self.expected_pci_interfaces = ['sriov', 'pthru'] -class InterfaceComputeVlanOverDataEthernet(InterfaceHostTestCase): - def _setup_configuration(self): - # Setup a sample configuration where the personality is set to a - # compute and all interfaces are vlan interfaces over data ethernet - # interfaces. - self._create_test_common() - self._create_test_host(constants.COMPUTE) - port, iface = ( - self._create_ethernet_test( - 'data', - [constants.NETWORK_TYPE_PXEBOOT, constants.NETWORK_TYPE_DATA])) - self._create_ethernet_test('mgmt', constants.NETWORK_TYPE_MGMT) - self._create_ethernet_test('infra', constants.NETWORK_TYPE_INFRA) - self._create_vlan_test('vrs', constants.NETWORK_TYPE_DATA_VRS, 4, - iface) - self._create_vlan_test('data2', constants.NETWORK_TYPE_DATA, 5, - iface) - self._create_ethernet_test('sriov', - constants.NETWORK_TYPE_PCI_SRIOV) - self._create_ethernet_test('pthru', - constants.NETWORK_TYPE_PCI_PASSTHROUGH) - - def setUp(self): - super(InterfaceComputeVlanOverDataEthernet, self).setUp() - self.expected_platform_interfaces = ['data', 'mgmt', - 'eth2', 'infra', - 'vrs'] - self.expected_data_interfaces = ['data', 'data2'] - self.expected_pci_interfaces = ['sriov', 'pthru'] - - class InterfaceCpeEthernet(InterfaceHostTestCase): def _setup_configuration(self): # Setup a sample configuration where the personality is set to a @@ -1759,30 +1808,33 @@ class InterfaceCpeEthernet(InterfaceHostTestCase): # ethernet interfaces. self._create_test_common() self._create_test_host(constants.CONTROLLER) - self._create_ethernet_test('oam', constants.NETWORK_TYPE_OAM) - self._create_ethernet_test('mgmt', constants.NETWORK_TYPE_MGMT) - self._create_ethernet_test('infra', constants.NETWORK_TYPE_INFRA) - self._create_ethernet_test('vrs', constants.NETWORK_TYPE_DATA_VRS) - self._create_ethernet_test('data', constants.NETWORK_TYPE_DATA) - self._create_ethernet_test('sriov', + self._create_ethernet_test('oam', None, constants.NETWORK_TYPE_OAM) + self._create_ethernet_test('mgmt', None, constants.NETWORK_TYPE_MGMT) + self._create_ethernet_test('infra', None, constants.NETWORK_TYPE_INFRA) + 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', + self._create_ethernet_test('pthru', constants.INTERFACE_CLASS_PCI_PASSTHROUGH, constants.NETWORK_TYPE_PCI_PASSTHROUGH) port, iface = ( - self._create_ethernet_test('slow', constants.NETWORK_TYPE_DATA, + self._create_ethernet_test('slow', constants.INTERFACE_CLASS_DATA, + constants.NETWORK_TYPE_DATA, dpdksupport=False)) port, iface = ( - self._create_ethernet_test('mlx4', constants.NETWORK_TYPE_DATA, + self._create_ethernet_test('mlx4', constants.INTERFACE_CLASS_DATA, + constants.NETWORK_TYPE_DATA, driver=interface.DRIVER_MLX_CX3)) port, iface = ( - self._create_ethernet_test('mlx5', constants.NETWORK_TYPE_DATA, + self._create_ethernet_test('mlx5', constants.INTERFACE_CLASS_DATA, + constants.NETWORK_TYPE_DATA, driver=interface.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', 'infra', 'vrs'] + self.expected_platform_interfaces = ['oam', 'mgmt', 'infra'] self.expected_data_interfaces = ['slow', 'data', 'mlx4', 'mlx5'] self.expected_pci_interfaces = ['sriov', 'pthru'] self.expected_slow_interfaces = ['slow'] @@ -1799,25 +1851,24 @@ class InterfaceCpeVlanOverEthernet(InterfaceHostTestCase): self._create_test_common() self._create_test_host(constants.CONTROLLER) port, iface = self._create_ethernet_test( - 'pxeboot', constants.NETWORK_TYPE_PXEBOOT) - self._create_vlan_test('oam', constants.NETWORK_TYPE_OAM, 1, iface) - self._create_vlan_test('mgmt', constants.NETWORK_TYPE_MGMT, 2, + 'pxeboot', None, constants.NETWORK_TYPE_PXEBOOT) + self._create_vlan_test('oam', None, constants.NETWORK_TYPE_OAM, 1, iface) + self._create_vlan_test('mgmt', None, constants.NETWORK_TYPE_MGMT, 2, iface) - self._create_vlan_test('infra', constants.NETWORK_TYPE_INFRA, 3) - self._create_vlan_test('vrs', constants.NETWORK_TYPE_DATA_VRS, 4) - self._create_vlan_test('data', constants.NETWORK_TYPE_DATA, 5) - self._create_ethernet_test('sriov', + self._create_vlan_test('infra', None, constants.NETWORK_TYPE_INFRA, 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', + 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', 'infra', - 'eth5', 'vrs'] - self.expected_data_interfaces = ['eth7', 'data'] + 'eth3', 'infra'] + self.expected_data_interfaces = ['eth5', 'data'] self.expected_pci_interfaces = ['sriov', 'pthru'] @@ -1828,14 +1879,14 @@ class InterfaceCpeBond(InterfaceHostTestCase): # aggregated ethernet interfaces. self._create_test_common() self._create_test_host(constants.CONTROLLER) - self._create_bond_test('oam', constants.NETWORK_TYPE_OAM) - self._create_bond_test('mgmt', constants.NETWORK_TYPE_MGMT) - self._create_bond_test('infra', constants.NETWORK_TYPE_INFRA) - self._create_bond_test('vrs', constants.NETWORK_TYPE_DATA_VRS) - self._create_bond_test('data', constants.NETWORK_TYPE_DATA) - self._create_ethernet_test('sriov', + self._create_bond_test('oam', None, constants.NETWORK_TYPE_OAM) + self._create_bond_test('mgmt', None, constants.NETWORK_TYPE_MGMT) + self._create_bond_test('infra', None, constants.NETWORK_TYPE_INFRA) + 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', + self._create_ethernet_test('pthru', constants.INTERFACE_CLASS_PCI_PASSTHROUGH, constants.NETWORK_TYPE_PCI_PASSTHROUGH) def setUp(self): @@ -1843,9 +1894,8 @@ class InterfaceCpeBond(InterfaceHostTestCase): self.expected_bmc_interface = 'mgmt' self.expected_platform_interfaces = ['eth0', 'eth1', 'oam', 'eth3', 'eth4', 'mgmt', - 'eth6', 'eth7', 'infra', - 'eth9', 'eth10', 'vrs'] - self.expected_data_interfaces = ['eth12', 'eth13', 'data'] + 'eth6', 'eth7', 'infra'] + 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', @@ -1859,65 +1909,28 @@ class InterfaceCpeVlanOverBond(InterfaceHostTestCase): # vlan interfaces over aggregated ethernet interfaces. self._create_test_common() self._create_test_host(constants.CONTROLLER) - bond = self._create_bond_test('pxeboot', + bond = self._create_bond_test('pxeboot', None, constants.NETWORK_TYPE_PXEBOOT) - self._create_vlan_test('oam', constants.NETWORK_TYPE_OAM, 1, bond) - self._create_vlan_test('mgmt', constants.NETWORK_TYPE_MGMT, 2, bond) - self._create_vlan_test('infra', constants.NETWORK_TYPE_INFRA, 3, + self._create_vlan_test('oam', None, constants.NETWORK_TYPE_OAM, 1, bond) + self._create_vlan_test('mgmt', None, constants.NETWORK_TYPE_MGMT, 2, bond) + self._create_vlan_test('infra', None, constants.NETWORK_TYPE_INFRA, 3, bond) - bond1 = self._create_bond_test('bond3') - self._create_vlan_test('vrs', constants.NETWORK_TYPE_DATA_VRS, 4, - bond1) bond2 = self._create_bond_test('bond4') - self._create_vlan_test('data', constants.NETWORK_TYPE_DATA, 5, + self._create_vlan_test('data', constants.INTERFACE_CLASS_DATA, + constants.NETWORK_TYPE_DATA, 5, bond2) - self._create_ethernet_test('sriov', + self._create_ethernet_test('sriov', constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV) - self._create_ethernet_test('pthru', + 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', 'infra', - 'eth6', 'eth7', 'bond3', 'vrs'] - self.expected_data_interfaces = ['eth10', 'eth11', 'bond4', 'data'] + 'oam', 'mgmt', 'infra'] + self.expected_data_interfaces = ['eth6', 'eth7', 'bond4', 'data'] self.expected_slave_interfaces = ['eth0', 'eth1', - 'eth6', 'eth7', - 'eth10', 'eth11'] - self.expected_pci_interfaces = ['sriov', 'pthru'] - - -class InterfaceCpeVlanOverDataEthernet(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 data ethernet interfaces. - self._create_test_common() - self._create_test_host(constants.CONTROLLER) - port, iface = ( - self._create_ethernet_test( - 'data', - [constants.NETWORK_TYPE_PXEBOOT, constants.NETWORK_TYPE_DATA])) - self._create_vlan_test('oam', constants.NETWORK_TYPE_OAM, 1, iface) - self._create_vlan_test('mgmt', constants.NETWORK_TYPE_MGMT, 2, - iface) - self._create_vlan_test('infra', constants.NETWORK_TYPE_INFRA, 3, - iface) - self._create_vlan_test('vrs', constants.NETWORK_TYPE_DATA_VRS, 4, - iface) - self._create_vlan_test('data2', constants.NETWORK_TYPE_DATA, 5, - iface) - self._create_ethernet_test('sriov', - constants.NETWORK_TYPE_PCI_SRIOV) - self._create_ethernet_test('pthru', - constants.NETWORK_TYPE_PCI_PASSTHROUGH) - - def setUp(self): - super(InterfaceCpeVlanOverDataEthernet, self).setUp() - self.expected_platform_interfaces = ['data', 'oam', 'mgmt', - 'infra', 'vrs'] - self.expected_data_interfaces = ['data', 'data2'] + 'eth6', 'eth7'] self.expected_pci_interfaces = ['sriov', 'pthru'] @@ -1928,30 +1941,33 @@ class InterfaceCpeComputeEthernet(InterfaceHostTestCase): # ethernet interfaces. self._create_test_common() self._create_test_host(constants.CONTROLLER, constants.COMPUTE) - self._create_ethernet_test('oam', constants.NETWORK_TYPE_OAM) - self._create_ethernet_test('mgmt', constants.NETWORK_TYPE_MGMT) - self._create_ethernet_test('infra', constants.NETWORK_TYPE_INFRA) - self._create_ethernet_test('vrs', constants.NETWORK_TYPE_DATA_VRS) - self._create_ethernet_test('data', constants.NETWORK_TYPE_DATA) - self._create_ethernet_test('sriov', + self._create_ethernet_test('oam', None, constants.NETWORK_TYPE_OAM) + self._create_ethernet_test('mgmt', None, constants.NETWORK_TYPE_MGMT) + self._create_ethernet_test('infra', None, constants.NETWORK_TYPE_INFRA) + 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', + self._create_ethernet_test('pthru', constants.INTERFACE_CLASS_PCI_PASSTHROUGH, constants.NETWORK_TYPE_PCI_PASSTHROUGH) port, iface = ( - self._create_ethernet_test('slow', constants.NETWORK_TYPE_DATA, + self._create_ethernet_test('slow', constants.INTERFACE_CLASS_DATA, + constants.NETWORK_TYPE_DATA, dpdksupport=False)) port, iface = ( - self._create_ethernet_test('mlx4', constants.NETWORK_TYPE_DATA, + self._create_ethernet_test('mlx4', constants.INTERFACE_CLASS_DATA, + constants.NETWORK_TYPE_DATA, driver=interface.DRIVER_MLX_CX3)) port, iface = ( - self._create_ethernet_test('mlx5', constants.NETWORK_TYPE_DATA, + self._create_ethernet_test('mlx5', constants.INTERFACE_CLASS_DATA, + constants.NETWORK_TYPE_DATA, driver=interface.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', 'infra', 'vrs'] + self.expected_platform_interfaces = ['oam', 'mgmt', 'infra'] self.expected_data_interfaces = ['slow', 'data', 'mlx4', 'mlx5'] self.expected_pci_interfaces = ['sriov', 'pthru'] self.expected_slow_interfaces = ['slow'] @@ -1968,25 +1984,24 @@ class InterfaceCpeComputeVlanOverEthernet(InterfaceHostTestCase): self._create_test_common() self._create_test_host(constants.CONTROLLER, constants.COMPUTE) port, iface = self._create_ethernet_test( - 'pxeboot', constants.NETWORK_TYPE_PXEBOOT) - self._create_vlan_test('oam', constants.NETWORK_TYPE_OAM, 1, iface) - self._create_vlan_test('mgmt', constants.NETWORK_TYPE_MGMT, 2, + 'pxeboot', None, constants.NETWORK_TYPE_PXEBOOT) + self._create_vlan_test('oam', None, constants.NETWORK_TYPE_OAM, 1, iface) + self._create_vlan_test('mgmt', None, constants.NETWORK_TYPE_MGMT, 2, iface) - self._create_vlan_test('infra', constants.NETWORK_TYPE_INFRA, 3) - self._create_vlan_test('vrs', constants.NETWORK_TYPE_DATA_VRS, 4) - self._create_vlan_test('data', constants.NETWORK_TYPE_DATA, 5) - self._create_ethernet_test('sriov', + self._create_vlan_test('infra', None, constants.NETWORK_TYPE_INFRA, 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', + 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', 'infra', - 'eth5', 'vrs'] - self.expected_data_interfaces = ['eth7', 'data'] + 'eth3', 'infra'] + self.expected_data_interfaces = ['eth5', 'data'] self.expected_pci_interfaces = ['sriov', 'pthru'] @@ -1997,14 +2012,14 @@ class InterfaceCpeComputeBond(InterfaceHostTestCase): # aggregated ethernet interfaces. self._create_test_common() self._create_test_host(constants.CONTROLLER, constants.COMPUTE) - self._create_bond_test('oam', constants.NETWORK_TYPE_OAM) - self._create_bond_test('mgmt', constants.NETWORK_TYPE_MGMT) - self._create_bond_test('infra', constants.NETWORK_TYPE_INFRA) - self._create_bond_test('vrs', constants.NETWORK_TYPE_DATA_VRS) - self._create_bond_test('data', constants.NETWORK_TYPE_DATA) - self._create_ethernet_test('sriov', + self._create_bond_test('oam', None, constants.NETWORK_TYPE_OAM) + self._create_bond_test('mgmt', None, constants.NETWORK_TYPE_MGMT) + self._create_bond_test('infra', None, constants.NETWORK_TYPE_INFRA) + 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', + self._create_ethernet_test('pthru', constants.INTERFACE_CLASS_PCI_PASSTHROUGH, constants.NETWORK_TYPE_PCI_PASSTHROUGH) def setUp(self): @@ -2012,9 +2027,8 @@ class InterfaceCpeComputeBond(InterfaceHostTestCase): self.expected_bmc_interface = 'mgmt' self.expected_platform_interfaces = ['eth0', 'eth1', 'oam', 'eth3', 'eth4', 'mgmt', - 'eth6', 'eth7', 'infra', - 'eth9', 'eth10', 'vrs'] - self.expected_data_interfaces = ['eth12', 'eth13', 'data'] + 'eth6', 'eth7', 'infra'] + 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', @@ -2028,61 +2042,26 @@ class InterfaceCpeComputeVlanOverBond(InterfaceHostTestCase): # vlan interfaces over aggregated ethernet interfaces. self._create_test_common() self._create_test_host(constants.CONTROLLER, constants.COMPUTE) - bond = self._create_bond_test('pxeboot', + bond = self._create_bond_test('pxeboot', None, constants.NETWORK_TYPE_PXEBOOT) - self._create_vlan_test('oam', constants.NETWORK_TYPE_OAM, 1, bond) - self._create_vlan_test('mgmt', constants.NETWORK_TYPE_MGMT, 2, bond) - self._create_vlan_test('infra', constants.NETWORK_TYPE_INFRA, 3, + self._create_vlan_test('oam', None, constants.NETWORK_TYPE_OAM, 1, bond) + self._create_vlan_test('mgmt', None, constants.NETWORK_TYPE_MGMT, 2, bond) + self._create_vlan_test('infra', None, constants.NETWORK_TYPE_INFRA, 3, bond) - bond1 = self._create_bond_test('bond1') - self._create_vlan_test('vrs', constants.NETWORK_TYPE_DATA_VRS, 4, - bond1) bond2 = self._create_bond_test('bond2') - self._create_vlan_test('data', constants.NETWORK_TYPE_DATA, 5, + self._create_vlan_test('data', constants.INTERFACE_CLASS_DATA, + constants.NETWORK_TYPE_DATA, 5, bond2) - self._create_ethernet_test('sriov', + self._create_ethernet_test('sriov', constants.INTERFACE_CLASS_PCI_SRIOV, constants.NETWORK_TYPE_PCI_SRIOV) - self._create_ethernet_test('pthru', + 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', 'infra', - 'eth6', 'eth7', 'bond1', 'vrs'] - self.expected_data_interfaces = ['eth10', 'eth11', 'bond2', 'data'] + 'oam', 'mgmt', 'infra'] + self.expected_data_interfaces = ['eth6', 'eth7', 'bond2', 'data'] self.expected_slave_interfaces = ['eth0', 'eth1', - 'eth6', 'eth7', - 'eth10', 'eth11'] - self.expected_pci_interfaces = ['sriov', 'pthru'] - - -class InterfaceCpeComputeVlanOverDataEthernet(InterfaceHostTestCase): - def _setup_configuration(self): - # Setup a sample configuration where the personality is set to a - # controller with a compute subfunction and all interfaces are - # vlan interfaces over data ethernet interfaces. - self._create_test_common() - self._create_test_host(constants.CONTROLLER, constants.COMPUTE) - port, iface = ( - self._create_ethernet_test( - 'data', - [constants.NETWORK_TYPE_PXEBOOT, constants.NETWORK_TYPE_DATA])) - self._create_ethernet_test('oam', constants.NETWORK_TYPE_OAM) - self._create_ethernet_test('mgmt', constants.NETWORK_TYPE_MGMT) - self._create_ethernet_test('infra', constants.NETWORK_TYPE_INFRA) - self._create_vlan_test('vrs', constants.NETWORK_TYPE_DATA_VRS, 4, - iface) - self._create_vlan_test('data2', constants.NETWORK_TYPE_DATA, 5, - iface) - self._create_ethernet_test('sriov', - constants.NETWORK_TYPE_PCI_SRIOV) - self._create_ethernet_test('pthru', - constants.NETWORK_TYPE_PCI_PASSTHROUGH) - - def setUp(self): - super(InterfaceCpeComputeVlanOverDataEthernet, self).setUp() - self.expected_platform_interfaces = ['data', 'oam', 'mgmt', - 'infra', 'vrs'] - self.expected_data_interfaces = ['data', 'data2'] + 'eth6', 'eth7'] self.expected_pci_interfaces = ['sriov', 'pthru']