Clean up interface network assignment

The networktype field is no longer used in the interface table
since an interface can have multiple networks associated with it.
This commit is to remove the networktype field and use the
network association instead.

The host interface commands used to allow associating an initial
network to the interface. This has been changed such that network
association can only be done with the interface-network commands.

The address assignment of an interface is performed when a network
is assigned to an interface, not when the interface is provisioned.

Data interface no longer requires at least one datanetwork
associated with it.

The REST API doc is also updated to reflect the changes.

Story: 2004273
Task: 30947
Task: 33504

Change-Id: I952008408826f4c630246477d71687628357622c
Signed-off-by: Teresa Ho <teresa.ho@windriver.com>
This commit is contained in:
Teresa Ho 2019-05-27 11:33:39 -04:00
parent f567ff1b52
commit 78bcf995fb
34 changed files with 715 additions and 1018 deletions

View File

@ -2406,7 +2406,6 @@ itemNotFound (404)
"aemode (Optional)", "plain", "xsd:string", "Only applicable if ``iftype : ae``, this attribute indicates the basic mode of operation for the AE/LAG interface. Supported modes are: balanced round robin, active-backup, balanced xor, broadcast, 802.3ad, balance-tlb, balance-alb. NOTE only balanced xor and active-standby modes are supported by interfaces of ifclass=data."
"txhashpolicy (Optional)", "plain", "xsd:string", "Only applicable if ``iftype : ae`` and ``aemode : balanced``, this attribute indicates what packet headers the AE/LAG is using to distribute packets across the different links/ports of the AE/LAG group; ``layer2``, ``layer2+3`` or ``layer3+4``."
"vlan_id (Optional)", "plain", "xsd:integer", "Only applicable if ``iftype : vlan``, this attribute indicates that the vlan interface id. A vlan id between 1 and 4094 (inclusive) must be selected. NOTE The vlan id must be unique for the host interface."
"networks (Optional)", "plain", "xsd:list", "Only applicable if ``ifclass : platform``, this attribute provides a list of platform networks that this interface is attached to."
"datanetworks (Optional)", "plain", "xsd:list", "Only applicable if ``ifclass : data``, this attribute provides a list of data networks that this ``data`` interface is attached to."
"imac (Optional)", "plain", "xsd:string", "The MAC Address being used by the interface. In the case of AE/LAG, the MAC address of one of the physical ports of the AE/LAG group is used."
"imtu (Optional)", "plain", "xsd:integer", "The Maximum Transmission Unit (MTU) of the interface, in bytes."
@ -2447,7 +2446,6 @@ itemNotFound (404)
"vlan_id": null,
"imtu": 1500,
"aemode": null,
"networks": ["1"],
"datanetworks": [],
"ifclass": "platform"
"ifname": "eth1"
@ -2480,7 +2478,6 @@ itemNotFound (404)
],
"aemode": "balanced",
"networks": [],
"datanetworks": ["physnet-0,physnet-1"],
"ifclass": "data"
"ifname": "data1"
@ -2526,7 +2523,6 @@ itemNotFound (404)
"aemode (Optional)", "plain", "xsd:string", "Only applicable if ``iftype : ae``, this attribute indicates the basic mode of operation for the AE/LAG interface. Supported modes are: balanced round robin, active-backup, balanced xor, broadcast, 802.3ad, balance-tlb, balance-alb. NOTE only balanced xor and active-standby modes are supported by interfaces of ifclass=data."
"txhashpolicy (Optional)", "plain", "xsd:string", "Only applicable if ``iftype : ae`` and ``aemode : balanced``, this attribute indicates what packet headers the AE/LAG is using to distribute packets across the different links/ports of the AE/LAG group; ``layer2``, ``layer2+3`` or ``layer3+4``."
"vlan_id (Optional)", "plain", "xsd:integer", "Only applicable if ``iftype : vlan``, this attribute indicates that the vlan interface id. A vlan id between 1 and 4094 (inclusive) must be selected. NOTE The vlan id must be unique for the host interface."
"networks (Optional)", "plain", "xsd:list", "Only applicable if ``ifclass : platform``, this attribute provides a list of platform networks that this interface is attached to."
"datanetworks (Optional)", "plain", "xsd:list", "Only applicable if ``ifclass : data``, this attribute provides a list of data networks that this ``data`` interface is attached to."
"imac (Optional)", "plain", "xsd:string", "The MAC Address being used by the interface. In the case of AE/LAG, the MAC address of one of the physical ports of the AE/LAG group is used."
"imtu (Optional)", "plain", "xsd:integer", "The Maximum Transmission Unit (MTU) of the interface, in bytes."
@ -2557,7 +2553,6 @@ itemNotFound (404)
}
],
"datanetworks" : ["physnet-0,physnet-1"],
"networks": [],
"txhashpolicy" : "layer2",
"schedpolicy" : null,
"uuid" : "740a5bec-b7a8-4645-93ed-aea0d4cfbf86",
@ -2622,7 +2617,6 @@ badMediaType (415)
"aemode (Optional)", "plain", "xsd:string", "Only applicable if ``iftype : ae``, this attribute specifies whether the AE/LAG should operate as ``balanced`` or ``active_standby`` or ``802.3ad`` across its links. The ``balanced`` and ``active_standby`` are the only modes supported by ``data`` type interface. For ``mgmt`` type interface the ``802.3ad`` option must be selected."
"txhashpolicy (Optional)", "plain", "xsd:string", "Only applicable if ``iftype : ae`` and ``aemode : balanced``, this attribute specifies what packet headers the AE/LAG should use to distribute packets across the different links/ports of the AE/LAG group; ``layer2``, ``layer2+3`` or ``layer3+4``."
"vlan_id (Optional)", "plain", "xsd:integer", "Only applicable if ``iftype : vlan``, this attribute specifies a virtual lan id for a vlan interface type."
"networks (Optional)", "plain", "xsd:list", "Only applicable if ``ifclass : platform``, this attribute provides a list of platform networks that this interface is attached to."
"datanetworks (Optional)", "plain", "xsd:list", "Only applicable if ``ifclass : data``, this attribute specifies a list of data networks that this ``data`` interface is attached to."
"ports (Optional)", "plain", "xsd:list", "This attribute specifies a comma-separated list of ports that this interface contains. If ``iftype : ethernet`` then only one port is allowed."
"uses (Optional)", "plain", "xsd:list", "Only applicable if ``iftype : ae`` or ``iftype: vlan``, this attribute specifies a comma-separated list of interfaces that this interface uses."
@ -2643,7 +2637,6 @@ badMediaType (415)
"aemode (Optional)", "plain", "xsd:string", "Only applicable if ``iftype : ae``, this attribute indicates the basic mode of operation for the AE/LAG interface. Supported modes are: balanced round robin, active-backup, balanced xor, broadcast, 802.3ad, balance-tlb, balance-alb. NOTE only balanced xor and active-standby modes are supported by interfaces of ifclass=data."
"txhashpolicy (Optional)", "plain", "xsd:string", "Only applicable if ``iftype : ae`` and ``aemode : balanced``, this attribute indicates what packet headers the AE/LAG is using to distribute packets across the different links/ports of the AE/LAG group; ``layer2``, ``layer2+3`` or ``layer3+4``."
"vlan_id (Optional)", "plain", "xsd:integer", "Only applicable if ``iftype : vlan``, this attribute indicates that the vlan interface id. A vlan id between 1 and 4094 (inclusive) must be selected. NOTE The vlan id must be unique for the host interface."
"networks (Optional)", "plain", "xsd:list", "Only applicable if ``ifclass : platform``, this attribute provides a list of platform networks that this interface is attached to."
"datanetworks (Optional)", "plain", "xsd:list", "Only applicable if ``ifclass : data``, this attribute provides a list of data networks that this ``data`` interface is attached to."
"imac (Optional)", "plain", "xsd:string", "The MAC Address being used by the interface. In the case of AE/LAG, the MAC address of one of the physical ports of the AE/LAG group is used."
"imtu (Optional)", "plain", "xsd:integer", "The Maximum Transmission Unit (MTU) of the interface, in bytes."
@ -2667,7 +2660,6 @@ badMediaType (415)
"txhashpolicy": "layer2",
"ihost_uuid": "ff453a51-1d3b-437f-a65e-b2d163f79f85",
"imtu": "1500",
"networks": [],
"datanetworks": "physnet-0,physnet1",
"ifclass": "data",
"ifname": "data1",
@ -2722,7 +2714,6 @@ badMediaType (415)
],
"aemode": "balanced",
"sriov_numvfs": 0,
'networks": [],
"datanetworks": ["physnet-0,physnet-1"],
"ifclass": "data",
"ifname": "data1",
@ -2757,7 +2748,6 @@ badMediaType (415)
"aemode (Optional)", "plain", "xsd:string", "Only applicable if ``iftype : ae``, this attribute specifies whether the AE/LAG should operate as ``balanced`` or ``active_standby`` across its links. These are the only modes supported by ``data`` type interface."
"txhashpolicy (Optional)", "plain", "xsd:string", "Only applicable if ``iftype : ae`` and ``aemode : balanced``, this attribute specifies what packet headers the AE/LAG should use to distribute packets across the different links/ports of the AE/LAG group; ``layer2``, ``layer2+3`` or ``layer3+4``."
"vlan_id (Optional)", "plain", "xsd:integer", "Only applicable if ``iftype : vlan``, this attribute specifies a virtual lan id for a vlan interface type."
"networks (Optional)", "plain", "xsd:list", "Only applicable if ``ifclass : platform``, this attribute provides a list of platform networks that this interface is attached to."
"datanetworks (Optional)", "plain", "xsd:list", "Only applicable if ``ifclass : data``, this attribute specifies a list of data networks that this ``data`` interface is attached to."
"ports (Optional)", "plain", "xsd:list", "This attribute specifies a comma-separated list of ports that this interface contains. If ``iftype : ethernet`` then only one port is allowed."
"uses (Optional)", "plain", "xsd:list", "Only applicable if ``iftype : ae`` or ``iftype: vlan``, this attribute specifies a comma-separated list of interfaces that this interface uses."
@ -2777,7 +2767,6 @@ badMediaType (415)
"aemode (Optional)", "plain", "xsd:string", "Only applicable if ``iftype : ae``, this attribute indicates the basic mode of operation for the AE/LAG interface. Supported modes are: balanced round robin, active-backup, balanced xor, broadcast, 802.3ad, balance-tlb, balance-alb. NOTE only balanced xor and active-standby modes are supported by interfaces of ifclass=data."
"txhashpolicy (Optional)", "plain", "xsd:string", "Only applicable if ``iftype : ae`` and ``aemode : balanced``, this attribute indicates what packet headers the AE/LAG is using to distribute packets across the different links/ports of the AE/LAG group; ``layer2``, ``layer2+3`` or ``layer3+4``."
"vlan_id (Optional)", "plain", "xsd:integer", "Only applicable if ``iftype : vlan``, this attribute indicates that the vlan interface id. A vlan id between 1 and 4094 (inclusive) must be selected. NOTE The vlan id must be unique for the host interface."
"networks (Optional)", "plain", "xsd:list", "Only applicable if ``ifclass : platform``, this attribute provides a list of platform networks that this interface is attached to."
"datanetworks (Optional)", "plain", "xsd:list", "Only applicable if ``ifclass : data``, this attribute provides a list of data networks that this ``data`` interface is attached to."
"imac (Optional)", "plain", "xsd:string", "The MAC Address being used by the interface. In the case of AE/LAG, the MAC address of one of the physical ports of the AE/LAG group is used."
"imtu (Optional)", "plain", "xsd:integer", "The Maximum Transmission Unit (MTU) of the interface, in bytes."
@ -2870,7 +2859,6 @@ badMediaType (415)
],
"aemode": "active_standby",
"networks": [],
"datanetworks": ["physnet-0,physnet-1"],
"ifclass": "data",
"ifname": "data1",

View File

@ -14,8 +14,9 @@
# Use shell instead of command module as source is an internal shell command
shell: "{{ item }}"
with_items:
- source /etc/platform/openrc; system host-if-add controller-0 lo virtual none lo -c platform --networks mgmt -m 1500
- source /etc/platform/openrc; system host-if-modify controller-0 -c platform --networks cluster-host lo
- source /etc/platform/openrc; system host-if-add controller-0 lo virtual none lo -c platform -m 1500
- source /etc/platform/openrc; system interface-network-assign controller-0 lo mgmt
- source /etc/platform/openrc; system interface-network-assign controller-0 lo cluster-host
- ip addr add {{ cluster_virtual }} brd {{ cluster_broadcast }} dev lo scope host label lo:5
- ip addr add {{ mgmt_virtual }} brd {{ management_broadcast }} dev lo scope host label lo:1
- ip addr add {{ pxe_virtual }} dev lo scope host

View File

@ -13,25 +13,17 @@ 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(cc, iinterface):
fields = ['ifname', 'iftype', 'ports', 'datanetworks',
'imac', 'imtu', 'ifclass', 'networks',
'imac', 'imtu', 'ifclass',
'aemode', 'schedpolicy', 'txhashpolicy',
'uuid', 'ihost_uuid',
'vlan_id', 'uses', 'used_by',
'created_at', 'updated_at', 'sriov_numvfs', 'sriov_vf_driver']
optional_fields = ['ipv4_mode', 'ipv6_mode', 'ipv4_pool', 'ipv6_pool']
rename_fields = [{'field': 'dpdksupport', 'label': 'accelerated'}]
network_names = ""
networks = getattr(iinterface, 'networks', [])
for n in networks:
network = network_utils._find_network(cc, n)
network_names += "{},".format(network.name)
network_names = network_names.strip(',')
setattr(iinterface, 'networks', network_names)
data = [(f, getattr(iinterface, f, '')) for f in fields]
data += [(f, getattr(iinterface, f, '')) for f in optional_fields
if hasattr(iinterface, f)]
@ -153,9 +145,6 @@ def do_host_if_delete(cc, args):
metavar='<class>',
choices=['platform', 'data', 'pci-passthrough', 'pci-sriov', 'none'],
help='The class of the interface')
@utils.arg('--networks',
metavar='<network name or id>',
help="Name or ID of network")
@utils.arg('portsorifaces',
metavar='<portsorifaces>',
nargs='+',
@ -177,7 +166,7 @@ def do_host_if_delete(cc, args):
def do_host_if_add(cc, args):
"""Add an interface."""
field_list = ['ifname', 'iftype', 'imtu', 'ifclass', 'networks', 'aemode',
field_list = ['ifname', 'iftype', 'imtu', 'ifclass', 'aemode',
'txhashpolicy', 'datanetworks', 'vlan_id',
'ipv4_mode', 'ipv6_mode', 'ipv4_pool', 'ipv6_pool']
@ -204,10 +193,6 @@ def do_host_if_add(cc, args):
user_specified_fields['datanetworks'] = \
user_specified_fields['datanetworks'].split(',')
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
user_specified_fields['uses'] = uses
@ -251,9 +236,6 @@ def do_host_if_add(cc, args):
@utils.arg('-c', '--ifclass',
metavar='<class>',
help='The class of the interface')
@utils.arg('--networks',
metavar='<network name or id>',
help="Name or ID of network")
@utils.arg('--ipv4-mode',
metavar='<ipv4_mode>',
choices=['disabled', 'static', 'pool'],
@ -281,7 +263,7 @@ def do_host_if_modify(cc, args):
"""Modify interface attributes."""
rwfields = ['iftype', 'ifname', 'imtu', 'aemode', 'txhashpolicy',
'datanetworks', 'providernetworks', 'ports', 'ifclass', 'networks',
'datanetworks', 'providernetworks', 'ports', 'ifclass',
'ipv4_mode', 'ipv6_mode', 'ipv4_pool', 'ipv6_pool',
'sriov_numvfs', 'sriov_vf_driver']
@ -303,10 +285,6 @@ 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 'ifclass' in user_specified_fields.keys():
if args.ifclass == 'none':

View File

@ -56,3 +56,11 @@ class InterfaceNetworkManager(base.Manager):
def remove(self, interface_network_uuid):
path = '/v1/interface_networks/%s' % interface_network_uuid
return self._delete(path)
def get_network_names(cc, interface):
network_names = []
ifnets = cc.interface_network.list_by_interface(interface.uuid)
for ifnet in ifnets:
network_names.append(getattr(ifnet, 'network_name'))
return network_names

View File

@ -16,6 +16,7 @@ from cgtsclient import exc
from cgtsclient.v1 import ethernetport as ethernetport_utils
from cgtsclient.v1 import icpu as icpu_utils
from cgtsclient.v1 import ihost as ihost_utils
from cgtsclient.v1 import interface_network as ifnet_utils
from cgtsclient.v1 import iprofile as iprofile_utils
import math
@ -58,11 +59,13 @@ def get_portconfig(iprofile):
return pstr
def get_interfaceconfig(iprofile):
def get_interfaceconfig(cc, iprofile):
istr = ''
for interface in iprofile.interfaces:
istr = istr + "%s: %s" % (interface.ifname, interface.networktype)
if interface.networktype == 'data':
if interface.ifclass == 'platform':
network_names = ifnet_utils.get_network_names(cc, interface)
istr = istr + "%s: %s" % (interface.ifname, network_names)
elif interface.ifclass == 'data':
istr = istr + "( %s )" % interface.datanetworks
_get_interface_ports_interfaces(iprofile, interface)
if interface.ports:
@ -83,7 +86,7 @@ def get_ifprofile_data(cc, iprofile):
if iprofile.ports: # an 'interface' profile
iprofile.portconfig = get_portconfig(iprofile)
iprofile.interfaces = cc.iprofile.list_iinterface(iprofile.uuid)
iprofile.interfaceconfig = get_interfaceconfig(iprofile)
iprofile.interfaceconfig = get_interfaceconfig(cc, iprofile)
def do_ifprofile_list(cc, args):
@ -91,7 +94,7 @@ def do_ifprofile_list(cc, args):
profiles = cc.iprofile.list_interface_profiles()
for profile in profiles:
profile.portconfig = get_portconfig(profile)
profile.interfaceconfig = get_interfaceconfig(profile)
profile.interfaceconfig = get_interfaceconfig(cc, profile)
field_labels = ['uuid', 'name', 'port config', 'interface config']
fields = ['uuid', 'profilename', 'portconfig', 'interfaceconfig']

View File

@ -213,22 +213,22 @@ class AgentManager(service.PeriodicService):
# do not bother with alarms since that adds too much noise.
LOG.info("Cross-numa performance degradation over port %s "
"on processor %d on host %s. Better performance "
"if you configure %s interface on port "
"if you configure platform interface on port "
"residing on processor 0, or configure a platform "
"core on processor %d." %
(info['name'], info['numa_node'], self.host,
info['networktype'], info['numa_node']))
info['numa_node']))
LOG.info("Affine %s interface %s with cpulist %s" %
(info['networktype'], info['name'], cpulist))
LOG.info("Affine platform interface %s with cpulist %s" %
(info['name'], cpulist))
cmd = '/usr/bin/affine-interrupts.sh %s %s' % \
(info['name'], cpulist)
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
proc.communicate()
LOG.info("%s return %d" % (cmd, proc.returncode))
if proc.returncode == 1:
LOG.error("Failed to affine %s %s interrupts with %s" %
(info['networktype'], info['name'], cpulist))
LOG.error("Failed to affine platform interface %s interrupts with %s" %
(info['name'], cpulist))
def _update_ttys_dcd_status(self, context, host_id):
# Retrieve the serial line carrier detect flag

View File

@ -246,11 +246,13 @@ class AddressController(rest.RestController):
def _check_interface_type(self, interface_id):
interface = pecan.request.dbapi.iinterface_get(interface_id)
if not interface.networktype:
raise exception.InterfaceNetworkTypeNotSet()
if interface.networktype not in ALLOWED_NETWORK_TYPES:
raise exception.UnsupportedInterfaceNetworkType(
networktype=interface.networktype)
if (interface['ifclass'] == constants.INTERFACE_TYPE_PLATFORM and
interface['networktypelist'] is None):
raise exception.InterfaceNetworkNotSet()
for nt in interface['networktypelist']:
if nt not in ALLOWED_NETWORK_TYPES:
raise exception.UnsupportedInterfaceNetworkType(
networktype=nt)
return
def _check_address_mode(self, interface_id, family):
@ -292,10 +294,9 @@ class AddressController(rest.RestController):
def _check_address_count(self, interface_id, host_id):
interface = pecan.request.dbapi.iinterface_get(interface_id)
networktype = interface['networktype']
sdn_enabled = utils.get_sdn_enabled()
if networktype == constants.NETWORK_TYPE_DATA and not sdn_enabled:
if interface['ifclass'] == constants.INTERFACE_CLASS_DATA and not sdn_enabled:
# Is permitted to add multiple addresses only
# if SDN L3 mode is not enabled.
return
@ -309,12 +310,12 @@ class AddressController(rest.RestController):
# skip the one we came in with
if uuid == interface_id:
continue
if iface['ifclass'] == constants.NETWORK_TYPE_DATA:
if iface['ifclass'] == constants.INTERFACE_CLASS_DATA:
addresses = (
pecan.request.dbapi.addresses_get_by_interface(uuid))
if len(addresses) != 0:
raise exception.\
AddressLimitedToOneWithSDN(iftype=networktype)
raise exception.AddressLimitedToOneWithSDN(
iftype=constants.INTERFACE_CLASS_DATA)
def _check_address_conflicts(self, host_id, interface_id, address):
self._check_address_count(interface_id, host_id)
@ -357,13 +358,14 @@ 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 = interface['networktype']
if networktype not in [constants.NETWORK_TYPE_MGMT,
constants.NETWORK_TYPE_OAM]:
return
network = pecan.request.dbapi.network_get_by_type(networktype)
if network.dynamic:
raise exception.StaticAddressNotConfigured()
if interface['networktypelist']:
for networktype in interface['networktypelist']:
if networktype not in [constants.NETWORK_TYPE_MGMT,
constants.NETWORK_TYPE_OAM]:
continue
network = pecan.request.dbapi.network_get_by_type(networktype)
if network.dynamic:
raise exception.StaticAddressNotConfigured()
host = pecan.request.dbapi.ihost_get(host_id)
if host['personality'] in [constants.STORAGE]:
raise exception.ManagedIPAddress()

View File

@ -3106,8 +3106,8 @@ class HostController(rest.RestController):
"""
count = 0
if interface.networktype not in address_api.ALLOWED_NETWORK_TYPES:
return
if not any(nt in address_api.ALLOWED_NETWORK_TYPES for nt in interface.networktypelist):
return
# Check IPv4 address presence
addresses = pecan.request.dbapi.addresses_get_by_interface(
interface['id'], family=constants.IPV4_FAMILY)
@ -3134,9 +3134,9 @@ class HostController(rest.RestController):
raise wsme.exc.ClientSideError(msg)
if min_count and (count < min_count):
msg = (_("Expecting at least %(min)s IP address(es) on "
"%(networktype)s interface %(ifname)s; found %(count)s") %
"%(ifclass)s interface %(ifname)s; found %(count)s") %
{'min': min_count,
'networktype': interface.networktype,
'ifclass': interface.ifclass,
'ifname': interface.ifname,
'count': count})
raise wsme.exc.ClientSideError(msg)
@ -3220,7 +3220,7 @@ class HostController(rest.RestController):
interfaces = (
pecan.request.dbapi.iinterface_get_by_ihost(ihost['uuid']))
for interface in interfaces:
if interface.networktype == constants.NETWORK_TYPE_OAM:
if constants.NETWORK_TYPE_OAM in interface.networktypelist:
break
else:
msg = _("Can not unlock a controller host without an oam "
@ -3333,7 +3333,7 @@ class HostController(rest.RestController):
address_count = 0
interfaces = pecan.request.dbapi.iinterface_get_by_ihost(ihost['uuid'])
for iface in interfaces:
if iface.networktype != constants.NETWORK_TYPE_DATA:
if iface.ifclass != constants.INTERFACE_TYPE_DATA:
continue
addresses = (
pecan.request.dbapi.addresses_get_by_interface(iface['uuid']))
@ -5900,11 +5900,10 @@ class HostController(rest.RestController):
# controller/worker/storage
ihost_iinterfaces = pecan.request.dbapi.iinterface_get_by_ihost(
ihost['uuid'])
network = pecan.request.dbapi.network_get_by_type(
constants.NETWORK_TYPE_MGMT)
mgmt_interface_configured = False
for iif in ihost_iinterfaces:
if iif.networks and str(network.id) in iif.networks:
if (iif.networktypelist and
constants.NETWORK_TYPE_MGMT in iif.networktypelist):
mgmt_interface_configured = True
if not mgmt_interface_configured:
@ -5917,10 +5916,9 @@ class HostController(rest.RestController):
# controller/worker/storage
host_interfaces = pecan.request.dbapi.iinterface_get_by_ihost(
ihost['uuid'])
network = pecan.request.dbapi.network_get_by_type(
constants.NETWORK_TYPE_CLUSTER_HOST)
for iif in host_interfaces:
if iif.networks and str(network.id) in iif.networks:
if (iif.networktypelist and
constants.NETWORK_TYPE_CLUSTER_HOST in iif.networktypelist):
break
else:
msg = _("Cannot unlock host %s "
@ -5969,15 +5967,9 @@ class HostController(rest.RestController):
# updated management interfaces
idata = {}
for iif in ihost_iinterfaces:
iif_networktype = []
if iif.networktype:
iif_networktype = [network.strip() for network in iif.networktype.split(",")]
if any(network in [constants.NETWORK_TYPE_MGMT] for network in iif_networktype):
if constants.NETWORK_TYPE_MGMT in iif.networktypelist:
for ila in interface_list_active:
ila_networktype = []
if ila.networktype:
ila_networktype = [network.strip() for network in ila.networktype.split(",")]
if any(network in ila_networktype for network in iif_networktype):
if constants.NETWORK_TYPE_MGMT in ila.networktypelist:
idata['imtu'] = ila.imtu
pecan.request.dbapi.iinterface_update(iif.uuid, idata)
break

File diff suppressed because it is too large Load Diff

View File

@ -200,8 +200,10 @@ class InterfaceDataNetworkController(rest.RestController):
pecan.request.dbapi.iinterface_update(interface_obj.uuid, values)
return
else:
# Allow ifclass data to assign another; disallow other ifclass
if interface_obj.ifclass != constants.INTERFACE_CLASS_DATA:
# Allow ifclass data, pcipt and sriov to assign data networks
if interface_obj.ifclass not in [constants.INTERFACE_CLASS_DATA,
constants.INTERFACE_CLASS_PCI_PASSTHROUGH,
constants.INTERFACE_CLASS_PCI_SRIOV]:
msg = _("An interface with interface class '%s' "
"cannot assign datanetworks." %
interface_obj.ifclass)

View File

@ -19,6 +19,7 @@
# Copyright (c) 2013-2018 Wind River Systems, Inc.
#
import os
import uuid
import wsme
import pecan
@ -26,6 +27,7 @@ from pecan import rest
from wsme import types as wtypes
import wsmeext.pecan as wsme_pecan
from sysinv.api.controllers.v1 import address_pool
from sysinv.api.controllers.v1 import base
from sysinv.api.controllers.v1 import collection
from sysinv.api.controllers.v1 import types
@ -134,8 +136,10 @@ class InterfaceNetworkController(rest.RestController):
interface_uuid = interface_network_dict.pop('interface_uuid')
network_uuid = interface_network_dict.pop('network_uuid')
interface_id = self._get_interface_id(interface_uuid)
interface_obj = pecan.request.dbapi.iinterface_get(interface_uuid)
interface_id = interface_obj.id
network_id, network_type = self._get_network_id_and_type(network_uuid)
host = pecan.request.dbapi.ihost_get(interface_obj.ihost_uuid)
interface_network_dict['interface_id'] = interface_id
interface_network_dict['network_id'] = network_id
@ -143,16 +147,51 @@ class InterfaceNetworkController(rest.RestController):
self._check_interface_class(interface_uuid)
self._check_assigned_network_type(network_type)
self._check_duplicate_interface_network(interface_network_dict)
self._check_duplicate_type(interface_id, network_type)
self._check_duplicate_type(host, interface_uuid, network_type)
self._check_pxeboot_network(interface_id, network_type)
self._check_oam_network(interface_id, network_type)
self._check_network_type_and_host_type(host, network_type)
self._check_network_type_and_interface_type(interface_obj, network_type)
self._check_cluster_host_on_controller(host, interface_obj, network_type)
result = pecan.request.dbapi.interface_network_create(interface_network_dict)
interface = pecan.request.dbapi.iinterface_get(interface_uuid)
if not interface.networktype:
values = {'networktype': network_type}
pecan.request.dbapi.iinterface_update(interface_uuid, values)
# Update address mode based on network type
if network_type in [constants.NETWORK_TYPE_MGMT,
constants.NETWORK_TYPE_OAM,
constants.NETWORK_TYPE_CLUSTER_HOST]:
pool_uuid = pecan.request.dbapi.network_get_by_type(network_type).pool_uuid
pool = pecan.request.dbapi.address_pool_get(pool_uuid)
if pool.family == constants.IPV4_FAMILY:
utils.update_address_mode(interface_obj, constants.IPV4_FAMILY,
constants.IPV4_STATIC, None)
utils.update_address_mode(interface_obj, constants.IPV6_FAMILY,
constants.IPV6_DISABLED, None)
else:
utils.update_address_mode(interface_obj, constants.IPV6_FAMILY,
constants.IPV6_STATIC, None)
utils.update_address_mode(interface_obj, constants.IPV4_FAMILY,
constants.IPV4_DISABLED, None)
# Assign an address to the interface
if host.recordtype != "profile":
_update_host_address(host, interface_obj, network_type)
if network_type == constants.NETWORK_TYPE_MGMT:
ethernet_port_mac = None
if not interface_obj.uses:
# Get the ethernet port associated with the interface
interface_ports = pecan.request.dbapi.ethernet_port_get_by_interface(
interface_obj.uuid)
for p in interface_ports:
if p is not None:
ethernet_port_mac = p.mac
break
else:
tmp_interface = interface_obj.as_dict()
ethernet_port_mac = tmp_interface['imac']
_update_host_mgmt_mac(host, ethernet_port_mac)
cutils.perform_distributed_cloud_config(pecan.request.dbapi,
interface_id)
return InterfaceNetwork.convert_with_links(result)
@ -218,16 +257,15 @@ class InterfaceNetworkController(rest.RestController):
% (interface_network['interface_id'], interface_network['network_id']))
raise wsme.exc.ClientSideError(msg)
def _check_duplicate_type(self, interface_id, network_type):
def _check_duplicate_type(self, host, interface_uuid, network_type):
if network_type in NONDUPLICATE_NETWORK_TYPES:
interface_networks = pecan.request.dbapi.interface_network_get_all()
for i in interface_networks:
if i.interface_id == interface_id and i.network_type == network_type:
msg = _("An interface with network type '%s' is "
"already provisioned on this node." % network_type)
interfaces = pecan.request.dbapi.iinterface_get_by_ihost(host['uuid'])
for host_interface in interfaces:
if (network_type in host_interface['networktypelist'] and
host_interface['uuid'] != interface_uuid):
msg = _("An interface with '%s' network type is "
"already provisioned on this node" % network_type)
raise wsme.exc.ClientSideError(msg)
else:
return
def _check_assigned_network_type(self, network_type):
if network_type not in NONASSIGNABLE_NETWORK_TYPES:
@ -275,6 +313,56 @@ class InterfaceNetworkController(rest.RestController):
% (i.network_type, network_type))
raise wsme.exc.ClientSideError(msg)
def _check_network_type_and_host_type(self, ihost, network_type):
if (network_type == constants.NETWORK_TYPE_OAM and
ihost['personality'] != constants.CONTROLLER):
msg = _("The '%s' network type is only supported on controller nodes." %
constants.NETWORK_TYPE_OAM)
raise wsme.exc.ClientSideError(msg)
def _check_network_type_and_interface_type(self, interface, network_type):
# Make sure network type 'mgmt', with if type 'ae',
# can only be in ae mode 'active_standby' or '802.3ad'
if (network_type == constants.NETWORK_TYPE_MGMT):
valid_mgmt_aemode = [constants.AE_MODE_LACP,
constants.AE_MODE_ACTIVE_STANDBY]
if (interface.iftype == constants.INTERFACE_TYPE_AE and
interface.aemode not in valid_mgmt_aemode):
msg = _("Device interface with network type {}, and interface "
"type 'aggregated ethernet' must be in mode {}").format(
network_type, ', '.join(valid_mgmt_aemode))
raise wsme.exc.ClientSideError(msg)
# Make sure network type 'oam' or 'cluster-host', with if type 'ae',
# can only be in ae mode 'active_standby' or 'balanced' or '802.3ad'
elif (network_type in [constants.NETWORK_TYPE_OAM,
constants.NETWORK_TYPE_CLUSTER_HOST] and
interface.iftype == constants.INTERFACE_TYPE_AE and
(interface.aemode not in constants.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'." % network_type)
raise wsme.exc.ClientSideError(msg)
def _check_cluster_host_on_controller(self, host, interface, network_type):
# Check if cluster-host exists on controller, if it doesn't then fail
if (host['personality'] != constants.CONTROLLER and
network_type == constants.NETWORK_TYPE_CLUSTER_HOST):
host_list = pecan.request.dbapi.ihost_get_by_personality(
personality=constants.CONTROLLER)
cluster_host_on_controller = False
for h in host_list:
interfaces = pecan.request.dbapi.iinterface_get_by_ihost(ihost=h['uuid'])
for host_interface in interfaces:
if (host_interface['ifclass'] == constants.INTERFACE_CLASS_PLATFORM and
constants.NETWORK_TYPE_CLUSTER_HOST in host_interface['networktypelist']):
cluster_host_on_controller = True
break
if not cluster_host_on_controller:
msg = _("Interface %s does not have associated"
" cluster-host interface on controller." %
interface['ifname'])
raise wsme.exc.ClientSideError(msg)
def _get_interface_id(self, interface_uuid):
interface = pecan.request.dbapi.iinterface_get(interface_uuid)
return interface['id']
@ -301,4 +389,125 @@ class InterfaceNetworkController(rest.RestController):
@cutils.synchronized(LOCK_NAME)
@wsme_pecan.wsexpose(None, types.uuid, status_code=204)
def delete(self, interface_network_uuid):
# Delete address allocated to the interface
if_network_obj = pecan.request.dbapi.interface_network_get(
interface_network_uuid)
network = pecan.request.dbapi.network_get(if_network_obj.network_uuid)
pool_uuid = pecan.request.dbapi.network_get_by_type(network.type).pool_uuid
address = None
try:
address = pecan.request.dbapi.addresses_get_by_interface_pool(
if_network_obj.interface_uuid, pool_uuid)
except exception.AddressNotFoundByInterfacePool:
pass
if address:
pecan.request.dbapi.address_remove_interface(address.uuid)
pecan.request.dbapi.interface_network_destroy(interface_network_uuid)
def _update_host_address(host, interface, network_type):
if network_type == constants.NETWORK_TYPE_MGMT:
_update_host_mgmt_address(host, interface)
elif network_type == constants.NETWORK_TYPE_CLUSTER_HOST:
_update_host_cluster_address(host, interface)
elif network_type == constants.NETWORK_TYPE_IRONIC:
_update_host_ironic_address(host, interface)
if host.personality == constants.CONTROLLER:
if network_type == constants.NETWORK_TYPE_OAM:
_update_host_oam_address(host, interface)
elif network_type == constants.NETWORK_TYPE_PXEBOOT:
_update_host_pxeboot_address(host, interface)
def _dynamic_address_allocation():
mgmt_network = pecan.request.dbapi.network_get_by_type(
constants.NETWORK_TYPE_MGMT)
return mgmt_network.dynamic
def _allocate_pool_address(interface_id, pool_uuid, address_name=None):
address_pool.AddressPoolController.assign_address(
interface_id, pool_uuid, address_name)
def _update_host_mgmt_address(host, interface):
"""Check if the host has a static management IP address assigned
and ensure the address is populated against the interface. Otherwise,
if using dynamic address allocation, then allocate an address
"""
mgmt_ip = utils.lookup_static_ip_address(
host.hostname, constants.NETWORK_TYPE_MGMT)
if mgmt_ip:
pecan.request.rpcapi.mgmt_ip_set_by_ihost(
pecan.request.context, host.uuid, interface['id'], mgmt_ip)
elif _dynamic_address_allocation():
mgmt_pool_uuid = pecan.request.dbapi.network_get_by_type(
constants.NETWORK_TYPE_MGMT
).pool_uuid
address_name = cutils.format_address_name(host.hostname,
constants.NETWORK_TYPE_MGMT)
_allocate_pool_address(interface['id'], mgmt_pool_uuid, address_name)
def _update_host_oam_address(host, interface):
if utils.get_system_mode() == constants.SYSTEM_MODE_SIMPLEX:
address_name = cutils.format_address_name(constants.CONTROLLER_HOSTNAME,
constants.NETWORK_TYPE_OAM)
else:
address_name = cutils.format_address_name(host.hostname,
constants.NETWORK_TYPE_OAM)
address = pecan.request.dbapi.address_get_by_name(address_name)
updates = {'interface_id': interface['id']}
pecan.request.dbapi.address_update(address.uuid, updates)
def _update_host_pxeboot_address(host, interface):
address_name = cutils.format_address_name(host.hostname,
constants.NETWORK_TYPE_PXEBOOT)
address = pecan.request.dbapi.address_get_by_name(address_name)
updates = {'interface_id': interface['id']}
pecan.request.dbapi.address_update(address.uuid, updates)
def _update_host_cluster_address(host, interface):
"""
Check if the host has a cluster-host IP address assigned
and the address is populated against the interface.
Otherwise, allocate an address from the pool.
"""
address_name = cutils.format_address_name(
host.hostname, constants.NETWORK_TYPE_CLUSTER_HOST)
try:
address = pecan.request.dbapi.address_get_by_name(address_name)
updates = {'interface_id': interface['id']}
pecan.request.dbapi.address_update(address.uuid, updates)
except exception.AddressNotFoundByName:
cluster_host_pool_uuid = pecan.request.dbapi.network_get_by_type(
constants.NETWORK_TYPE_CLUSTER_HOST
).pool_uuid
_allocate_pool_address(interface['id'], cluster_host_pool_uuid,
address_name)
def _update_host_ironic_address(host, interface):
address_name = cutils.format_address_name(host.hostname,
constants.NETWORK_TYPE_IRONIC)
address = pecan.request.dbapi.address_get_by_name(address_name)
updates = {'interface_id': interface['id']}
pecan.request.dbapi.address_update(address.uuid, updates)
def _update_host_mgmt_mac(host, mgmt_mac):
"""Update host mgmt mac to reflect interface change.
"""
if (os.path.isfile(constants.ANSIBLE_BOOTSTRAP_FLAG) and
mgmt_mac is not None):
# This must be called during management interface provisioning
# following controller-0 bootstrap.
if host['mgmt_mac'] != mgmt_mac:
pecan.request.rpcapi.mgmt_mac_set_by_ihost(
pecan.request.context, host, mgmt_mac)

View File

@ -35,6 +35,7 @@ from sysinv.api.controllers.v1 import cpu as cpu_api
from sysinv.api.controllers.v1 import disk as disk_api
from sysinv.api.controllers.v1 import partition as partition_api
from sysinv.api.controllers.v1 import interface as interface_api
from sysinv.api.controllers.v1 import interface_network as ifnet_api
from sysinv.api.controllers.v1 import memory as memory_api
from sysinv.api.controllers.v1 import node as node_api
from sysinv.api.controllers.v1 import storage as storage_api
@ -2022,6 +2023,13 @@ def ifprofile_copy_data(host, profile):
pdict = {k: v for (k, v) in p.as_dict().items() if k in ethernet_port_fields}
pecan.request.dbapi.ethernet_port_create(iprofile_id, pdict)
interface_networks = pecan.request.dbapi.interface_network_get_by_interface(i.id)
for ifnet in interface_networks:
ifnetdict = {}
ifnetdict['interface_id'] = newIf.id
ifnetdict['network_id'] = ifnet.network_id
pecan.request.dbapi.interface_network_create(ifnetdict)
# Generate the uses/used_by relationships
for i in newIfList:
uses_list = []
@ -2614,6 +2622,14 @@ def ifprofile_apply_to_host(host, profile):
if interface_found is False:
hinterface = interface_api._create(data, from_profile=True)
interface_networks = pecan.request.dbapi.interface_network_get_by_interface(interface.id)
for ifnet in interface_networks:
ifnetdict = {}
ifnetdict['interface_id'] = hinterface.id
ifnetdict['network_id'] = ifnet.network_id
pecan.request.dbapi.interface_network_create(ifnetdict)
network = pecan.request.dbapi.network_get_by_id(ifnet.network_id)
ifnet_api._update_host_address(host, hinterface, network.type)
except Exception as e:
# Delete all Host's interfaces
@ -2678,6 +2694,15 @@ def ifprofile_apply_to_host(host, profile):
data['forihostid'] = host.id
hinterface = interface_api._create(data, from_profile=True)
interface_networks = pecan.request.dbapi.interface_network_get_by_interface(i.id)
for ifnet in interface_networks:
ifnetdict = {}
ifnetdict['interface_id'] = hinterface.id
ifnetdict['network_id'] = ifnet.network_id
pecan.request.dbapi.interface_network_create(ifnetdict)
network = pecan.request.dbapi.network_get_by_id(ifnet.network_id)
ifnet_api._update_host_address(host, hinterface, network.type)
for r in profile.routes.get(i.uuid, []):
pecan.request.dbapi.route_create(hinterface.id, r)

View File

@ -263,9 +263,12 @@ class RouteController(rest.RestController):
def _check_interface_type(self, interface_id):
interface = pecan.request.dbapi.iinterface_get(interface_id)
networktype = interface['networktype']
if networktype not in ALLOWED_NETWORK_TYPES:
raise exception.RoutesNotSupportedOnInterfaces(iftype=networktype)
if (interface['ifclass'] == constants.INTERFACE_TYPE_PLATFORM and
interface['networktypelist'] is None):
raise exception.InterfaceNetworkNotSet()
for nt in interface['networktypelist']:
if nt not in ALLOWED_NETWORK_TYPES:
raise exception.RoutesNotSupportedOnInterfaces(type=nt)
return
def _check_duplicate_route(self, host_id, route):

View File

@ -598,11 +598,9 @@ class SystemController(rest.RestController):
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']
if constants.NETWORK_TYPE_MGMT in interface['networktypelist']:
if 'vlan_id' not in interface:
return 0
else:
return interface['vlan_id']
return None

View File

@ -326,6 +326,28 @@ def lookup_static_ip_address(name, networktype):
return None
def update_address_mode(interface, family, mode, pool):
interface_id = interface['id']
pool_id = pecan.request.dbapi.address_pool_get(pool)['id'] if pool else None
try:
# retrieve the existing value and compare
existing = pecan.request.dbapi.address_mode_query(
interface_id, family)
if existing.mode == mode:
if (mode != 'pool' or existing.pool_uuid == pool):
return
if existing.mode == 'pool' or (not mode or mode == 'disabled'):
pecan.request.dbapi.routes_destroy_by_interface(
interface_id, family)
pecan.request.dbapi.addresses_destroy_by_interface(
interface_id, family)
except exception.AddressModeNotFoundByFamily:
# continue and update DB with new record
pass
updates = {'family': family, 'mode': mode, 'address_pool_id': pool_id}
pecan.request.dbapi.address_mode_update(interface_id, updates)
class SystemHelper(object):
@staticmethod
def get_product_build():

View File

@ -651,6 +651,13 @@ INTERFACE_CLASS_DATA = 'data'
INTERFACE_CLASS_PCI_PASSTHROUGH = 'pci-passthrough'
INTERFACE_CLASS_PCI_SRIOV = 'pci-sriov'
AE_MODE_ACTIVE_STANDBY = 'active_standby'
AE_MODE_BALANCED = 'balanced'
AE_MODE_LACP = '802.3ad'
VALID_AEMODE_LIST = [AE_MODE_ACTIVE_STANDBY,
AE_MODE_BALANCED,
AE_MODE_LACP]
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"

View File

@ -331,9 +331,8 @@ class InterfaceNameAlreadyExists(Conflict):
message = _("Interface with name %(name)s already exists.")
class InterfaceNetworkTypeNotSet(Conflict):
message = _("The Interface must have a networktype configured to "
"support addresses. (data or infra)")
class InterfaceNetworkNotSet(Conflict):
message = _("The Interface does not have any network assigned to it.")
class AddressInUseByRouteGateway(Conflict):
@ -372,7 +371,7 @@ class RouteGatewayCannotBeLocal(Conflict):
class RoutesNotSupportedOnInterfaces(Conflict):
message = _("Routes may not be configured against interfaces with network "
"type '%(iftype)s'")
"type '%(type)s'")
class DefaultRouteNotAllowedOnVRSInterface(Conflict):
@ -699,6 +698,11 @@ class AddressNotFoundByName(NotFound):
message = _("Address could not be found for %(name)s")
class AddressNotFoundByInterfacePool(NotFound):
message = _("Address could not be found for interface %(interface)s "
"pool %(pool)s")
class AddressModeAlreadyExists(Conflict):
message = _("An AddressMode with UUID %(uuid)s already exists.")

View File

@ -1027,51 +1027,6 @@ def get_required_platform_reserved_memory(ihost, numa_node, low_core=False):
return required_reserved
def get_network_type_list(interface):
if interface['networktype']:
return [n.strip() for n in interface['networktype'].split(",")]
else:
return []
def is_pci_network_types(networktypelist):
"""
Check if the network type consists of the combined PCI passthrough
and SRIOV network types.
"""
return (len(constants.PCI_NETWORK_TYPES) == len(networktypelist) and
all(i in networktypelist for i in constants.PCI_NETWORK_TYPES))
def get_primary_network_type(interface):
"""
An interface can be associated with up to 2 network types but it can only
have 1 primary network type. The additional network type can only be
'data' and is used as a placeholder to indicate that there is at least one
VLAN based neutron provider network associated to the interface. This
information is used to determine whether the vswitch on the worker needs
to control the interface or not. This function examines the list of
network types, discards the secondary type (if any) and returns the primary
network type.
"""
if not interface['ifclass'] or interface['ifclass'] == constants.INTERFACE_CLASS_NONE:
return None
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():
return SW_VERSION
@ -1502,7 +1457,7 @@ def perform_distributed_cloud_config(dbapi, mgmt_iface_id):
mate_interfaces = dbapi.iinterface_get_all(
forihostid=mate_controller_id)
for interface in mate_interfaces:
if interface.networktype == constants.NETWORK_TYPE_MGMT:
if constants.NETWORK_TYPE_MGMT in interface.networktypelist:
mate_mgmt_iface = interface
break
else:

View File

@ -1196,7 +1196,7 @@ 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:
if interface.networktype == network_type:
if network_type in interface.networktypelist:
return cutils.get_interface_os_ifname(interface, ifaces, ports)
def _find_local_mgmt_interface_vlan_id(self):
@ -1204,7 +1204,7 @@ class ConductorManager(service.PeriodicService):
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 constants.NETWORK_TYPE_MGMT in interface.networktypelist:
if 'vlan_id' not in interface:
return 0
else:
@ -1820,7 +1820,7 @@ class ConductorManager(service.PeriodicService):
expunge=True)
for i in iinterfaces:
if i.networktype == constants.NETWORK_TYPE_MGMT:
if constants.NETWORK_TYPE_MGMT in i.networktypelist:
break
cloning = False
@ -1923,7 +1923,6 @@ class ConductorManager(service.PeriodicService):
'imtu': mtu,
'iftype': 'ethernet',
'ifclass': ifclass,
'networktype': networktype
}
# autocreate untagged interface
@ -1940,6 +1939,7 @@ class ConductorManager(service.PeriodicService):
})
if networktype in [constants.NETWORK_TYPE_MGMT,
constants.NETWORK_TYPE_PXEBOOT]:
new_interface_networktype = networktype
network = self.dbapi.network_get_by_type(networktype)
# create interface network association
ifnet_dict = {
@ -1960,6 +1960,7 @@ class ConductorManager(service.PeriodicService):
if create_tagged_interface:
# autocreate tagged management interface
network = self.dbapi.network_get_by_type(constants.NETWORK_TYPE_MGMT)
interface_dict = {
'forihostid': ihost['id'],
'ifname': 'mgmt0',
@ -1967,7 +1968,6 @@ class ConductorManager(service.PeriodicService):
'imtu': constants.DEFAULT_MTU,
'iftype': 'vlan',
'ifclass': constants.INTERFACE_CLASS_PLATFORM,
'networktype': constants.NETWORK_TYPE_MGMT,
'uses': [ifname],
'vlan_id': vlan_id,
}
@ -1978,6 +1978,7 @@ class ConductorManager(service.PeriodicService):
new_interface = self.dbapi.iinterface_create(
ihost['id'], interface_dict
)
new_interface_networktype = constants.NETWORK_TYPE_MGMT
network = self.dbapi.network_get_by_type(
constants.NETWORK_TYPE_MGMT
)
@ -2057,7 +2058,7 @@ class ConductorManager(service.PeriodicService):
values = {'interface_id': new_interface['id']}
try:
addr_name = cutils.format_address_name(
ihost.hostname, new_interface['networktype'])
ihost.hostname, new_interface_networktype)
address = self.dbapi.address_get_by_name(addr_name)
self.dbapi.address_update(address['uuid'], values)
except exception.AddressNotFoundByName:
@ -8449,7 +8450,8 @@ class ConductorManager(service.PeriodicService):
if nettype:
iinterfaces[:] = [i for i in iinterfaces if
i.networktype == nettype]
nettype in i.networktypelist]
return iinterfaces
def mgmt_ip_set_by_ihost(self,
@ -8604,13 +8606,12 @@ class ConductorManager(service.PeriodicService):
return ilvgs
def _add_port_to_list(self, interface_id, networktype, port_list):
def _add_port_to_list(self, interface_id, port_list):
info = {}
ports = self.dbapi.port_get_all(interfaceid=interface_id)
if ports:
info['name'] = ports[0]['name']
info['numa_node'] = ports[0]['numa_node']
info['networktype'] = networktype
if info not in port_list:
port_list.append(info)
return port_list
@ -8622,30 +8623,22 @@ class ConductorManager(service.PeriodicService):
info_list = []
interface_list = self.dbapi.iinterface_get_all(ihost_id, expunge=True)
for interface in interface_list:
ntype = interface['networktype']
if (ntype == constants.NETWORK_TYPE_CLUSTER_HOST or
ntype == constants.NETWORK_TYPE_MGMT):
if interface['iftype'] == 'vlan' or \
interface['iftype'] == 'ae':
if interface['ifclass'] == constants.INTERFACE_CLASS_PLATFORM:
if interface['iftype'] == constants.INTERFACE_TYPE_VLAN or \
interface['iftype'] == constants.INTERFACE_TYPE_AE:
for uses_if in interface['uses']:
for i in interface_list:
if i['ifname'] == str(uses_if):
if i['iftype'] == 'ethernet':
info_list = self._add_port_to_list(i['id'],
ntype,
lower_iface = self.dbapi.iinterface_get(uses_if, ihost_id)
if lower_iface['iftype'] == constants.INTERFACE_TYPE_ETHERNET:
info_list = self._add_port_to_list(lower_iface['id'],
info_list)
elif lower_iface['iftype'] == constants.INTERFACE_TYPE_AE:
for lower_uses_if in lower_iface['uses']:
ll_iface = self.dbapi.iinterface_get(lower_uses_if, ihost_id)
if ll_iface['iftype'] == constants.INTERFACE_TYPE_ETHERNET:
info_list = self._add_port_to_list(ll_iface['id'],
info_list)
elif i['iftype'] == 'ae':
for uses in i['uses']:
for a in interface_list:
if a['ifname'] == str(uses) and \
a['iftype'] == 'ethernet':
info_list = self._add_port_to_list(
a['id'],
ntype,
info_list)
elif interface['iftype'] == 'ethernet':
elif interface['iftype'] == constants.INTERFACE_TYPE_ETHERNET:
info_list = self._add_port_to_list(interface['id'],
ntype,
info_list)
LOG.info("platform_interfaces host_id=%s info_list=%s" %

View File

@ -842,7 +842,6 @@ class Connection(object):
{
'uuid': uuidutils.generate_uuid(),
'ifname': 'bond1',
'networktype': constants.NETWORK_TYPE_DATA,
'aemode': 'balanced',
'schedpolicy': 'xor',
'txhashpolicy': 'L2',
@ -934,7 +933,6 @@ class Connection(object):
{
'uuid': uuidutils.generate_uuid(),
'ifname': 'eth1',
'networktype': constants.NETWORK_TYPE_MGMT,
'extra': { ... },
}
:returns: An EthernetInterface.

View File

@ -2085,14 +2085,13 @@ class Connection(api.Connection):
query, models.ihost, [forihostid])
return query.all()
def _iinterface_get(self, iinterface_id, ihost=None, network=None):
def _iinterface_get(self, iinterface_id, ihost=None):
entity = with_polymorphic(models.Interfaces, '*')
query = model_query(entity)
query = add_interface_filter(query, iinterface_id)
if ihost is not None:
query = add_interface_filter_by_ihost(query, ihost)
if network is not None:
query = query.filter_by(networktype=network)
try:
result = query.one()
except NoResultFound:
@ -2106,7 +2105,7 @@ class Connection(api.Connection):
@objects.objectify(objects.interface)
def iinterface_get(self, iinterface_id, ihost=None, network=None):
return self._iinterface_get(iinterface_id, ihost, network)
return self._iinterface_get(iinterface_id, ihost)
@objects.objectify(objects.interface)
def iinterface_get_list(self, limit=None, marker=None,
@ -2155,16 +2154,6 @@ class Connection(api.Connection):
return _paginate_query(models.Interfaces, limit, marker,
sort_key, sort_dir, query)
@objects.objectify(objects.interface)
def iinterface_get_by_network(self, network,
limit=None, marker=None,
sort_key=None, sort_dir=None):
entity = with_polymorphic(models.Interfaces, '*')
query = model_query(entity)
query = query.filter_by(networktype=network)
return _paginate_query(models.Interfaces, limit, marker,
sort_key, sort_dir, query)
@objects.objectify(objects.interface)
def iinterface_update(self, iinterface_id, values):
with _session_for_write() as session:
@ -2237,13 +2226,6 @@ class Connection(api.Connection):
if obj.id is None:
obj.id = temp_id
# Ensure networktype results are None when they
# are specified as 'none'. Otherwise the 'none' value is written to
# the database which causes issues with checks that expects it to be
# the None type
if getattr(obj, 'networktype', None) == constants.NETWORK_TYPE_NONE:
setattr(obj, 'networktype', None)
try:
session.add(obj)
session.flush()
@ -2318,8 +2300,6 @@ class Connection(api.Connection):
obj = self._interface_get(models.Interfaces, interface_id)
for k, v in list(values.items()):
if k == 'networktype' and v == constants.NETWORK_TYPE_NONE:
v = None
if k == 'datanetworks' and v == 'none':
v = None
if k == 'uses':
@ -4952,6 +4932,26 @@ class Connection(api.Connection):
limit, marker,
sort_key, sort_dir)
@objects.objectify(objects.address)
def addresses_get_by_interface_pool(self, interface_uuid, pool_uuid,
limit=None, marker=None,
sort_key=None, sort_dir=None):
interface_id = self.iinterface_get(interface_uuid).id
pool_id = self.address_pool_get(pool_uuid).id
query = model_query(models.Addresses)
query = (query.
join(models.AddressPools,
models.AddressPools.id == pool_id).
join(models.Interfaces,
models.Interfaces.id == interface_id).
filter(models.Addresses.interface_id == interface_id).
filter(models.Addresses.address_pool_id == pool_id))
try:
result = query.one()
except NoResultFound:
raise exception.AddressNotFoundByInterfacePool(interface=interface_uuid, pool=pool_uuid)
return result
def address_destroy(self, address_uuid):
query = model_query(models.Addresses)
query = add_identity_filter(query, address_uuid)

View File

@ -0,0 +1,26 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright (c) 2019 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
interface = Table('interfaces', meta, autoload=True)
interface.drop_column('networktype')
return True
def downgrade(migrate_engine):
raise NotImplementedError('SysInv database downgrade is unsupported.')

View File

@ -339,7 +339,6 @@ class Interfaces(Base):
ifname = Column(String(255))
ifclass = Column(String(255))
networktype = Column(String(255))
ifcapabilities = Column(JSONEncodedDict)
farend = Column(JSONEncodedDict)
sriov_numvfs = Column(Integer)

View File

@ -355,12 +355,10 @@ class NeutronHelm(openstack.OpenstackBaseHelm):
return ml2_config
def _is_data_network_type(self, iface):
networktypelist = utils.get_network_type_list(iface)
return bool(any(n in DATA_NETWORK_TYPES for n in networktypelist))
return iface.ifclass == constants.INTERFACE_CLASS_DATA
def _is_sriov_network_type(self, iface):
networktypelist = utils.get_network_type_list(iface)
return bool(any(n in SRIOV_NETWORK_TYPES for n in networktypelist))
return iface.ifclass == constants.INTERFACE_CLASS_PCI_SRIOV
def _get_interface_datanets(self, iface):
"""

View File

@ -24,7 +24,6 @@ class Address(base.SysinvObject):
'forihostid': utils.int_or_none,
'interface_uuid': utils.uuid_or_none,
'pool_uuid': utils.uuid_or_none,
'networktype': utils.str_or_none,
'ifname': utils.str_or_none,
'family': utils.int_or_none,
'address': utils.ip_str_or_none(),
@ -36,8 +35,7 @@ class Address(base.SysinvObject):
_foreign_fields = {'interface_uuid': 'interface:uuid',
'pool_uuid': 'address_pool:uuid',
'ifname': 'interface:ifname',
'forihostid': 'interface:forihostid',
'networktype': 'interface:networktype'}
'forihostid': 'interface:forihostid'}
@base.remotable_classmethod
def get_by_uuid(cls, context, uuid):

View File

@ -78,12 +78,12 @@ def get_host_uuid(field, db_server):
return host_uuid
def get_networks(field, db_object):
def get_networktypes(field, db_object):
result = []
try:
if getattr(db_object, 'interface_networks', None):
for entry in getattr(db_object, 'interface_networks', []):
id_str = str(entry.network_id)
id_str = str(entry.network.type)
result.append(id_str)
except exc.DetachedInstanceError:
# instrument and return empty network
@ -126,11 +126,10 @@ class Interface(base.SysinvObject):
'ifclass': utils.str_or_none,
'imac': utils.str_or_none,
'imtu': utils.int_or_none,
'networktype': utils.str_or_none,
'aemode': utils.str_or_none,
'schedpolicy': utils.str_or_none,
'txhashpolicy': utils.str_or_none,
'networks': utils.list_of_strings_or_none,
'networktypelist': utils.list_of_strings_or_none,
'datanetworks': utils.list_of_strings_or_none,
'ifcapabilities': utils.dict_or_none,
@ -156,7 +155,7 @@ class Interface(base.SysinvObject):
'ipv4_pool': get_ipv4_address_pool,
'ipv6_pool': get_ipv6_address_pool,
'ihost_uuid': get_host_uuid,
'networks': get_networks,
'networktypelist': get_networktypes,
'datanetworks': get_datanetworks}
_optional_fields = ['aemode', 'txhashpolicy', 'schedpolicy',

View File

@ -24,7 +24,6 @@ class Route(base.SysinvObject):
'forihostid': utils.int_or_none,
'interface_uuid': utils.uuid_or_none,
'interface_id': int,
'networktype': utils.str_or_none,
'ifname': utils.str_or_none,
'family': utils.str_or_none,
'network': utils.ip_str_or_none(),
@ -36,8 +35,7 @@ class Route(base.SysinvObject):
_foreign_fields = {'interface_uuid': 'interface:uuid',
'interface_id': 'interface:id',
'ifname': 'interface:ifname',
'forihostid': 'interface:forihostid',
'networktype': 'interface:networktype'}
'forihostid': 'interface:forihostid'}
@base.remotable_classmethod
def get_by_uuid(cls, context, uuid):

View File

@ -99,8 +99,7 @@ def list_of_strings_or_none(val):
if not isinstance(val, list):
raise ValueError(_('A list of strings is required here'))
if not all([isinstance(x, six.string_types) for x in val]):
raise ValueError(_('Invalid values found in list '
'(strings are required)'))
raise ValueError(_('Invalid values %s found in list (strings are required)') % val)
return val

View File

@ -934,7 +934,7 @@ def get_common_network_config(context, iface, config, network_id=None):
layer interface (i.e., an interface that is used to terminate IP traffic).
"""
LOG.debug("get_common_network_config %s %s network_id=%s" %
(iface.ifname, iface.networks, network_id))
(iface.ifname, iface.networktypelist, network_id))
traffic_classifier = get_interface_traffic_classifier(context, iface,
network_id)
if traffic_classifier:
@ -967,7 +967,7 @@ def get_interface_network_config(context, iface, network_id=None):
# setup an alias interface if there are multiple addresses assigned
# NOTE: DHCP will only operate over a non-alias interface
if len(iface.networks) > 1 and network_id and method != DHCP_METHOD:
if len(iface.networktypelist) > 1 and network_id and method != DHCP_METHOD:
ifname = "%s:%d" % (os_ifname, network_id)
else:
ifname = os_ifname
@ -1012,8 +1012,9 @@ def generate_network_config(context, config, iface):
net_config['ifname']: format_network_config(net_config)
})
for net_id in iface.networks:
net_config = get_interface_network_config(context, iface, int(net_id))
for net_type in iface.networktypelist:
net_id = find_network_id_by_networktype(context, net_type)
net_config = get_interface_network_config(context, iface, net_id)
config[NETWORK_CONFIG_RESOURCE].update({
net_config['ifname']: format_network_config(net_config)
})
@ -1060,8 +1061,7 @@ def find_interface_by_type(context, networktype):
mgmt, cluster-host, pxeboot, bmc).
"""
for ifname, iface in six.iteritems(context['interfaces']):
for net_id in iface.networks:
net_type = find_networktype_by_network_id(context, int(net_id))
for net_type in iface.networktypelist:
if networktype == net_type:
return iface

View File

@ -723,16 +723,12 @@ class PlatformPuppet(base.BasePuppet):
# Calculate the optimal NFS r/w size based on the network mtu based
# on the configured network(s)
mtu = constants.DEFAULT_MTU
mgmt_network = self.dbapi.network_get_by_type(
constants.NETWORK_TYPE_MGMT)
network_id = mgmt_network.id
interfaces = self.dbapi.iinterface_get_by_ihost(host.uuid)
for interface in interfaces:
if interface['ifclass'] == constants.INTERFACE_CLASS_PLATFORM:
for net_id in interface['networks']:
if int(net_id) == network_id:
mtu = interface.imtu
break
if constants.NETWORK_TYPE_MGMT in interface['networktypelist']:
mtu = interface.imtu
break
if self._get_address_by_name(
constants.CONTROLLER_PLATFORM_NFS,

View File

@ -148,6 +148,7 @@ class InterfaceTestCase(base.FunctionalTest):
def setUp(self):
super(InterfaceTestCase, self).setUp()
self.dbapi = db_api.get_instance()
p = mock.patch.object(api_if_v1, '_get_lower_interface_macs')
self.mock_lower_macs = p.start()
self.mock_lower_macs.return_value = {'enp0s18': '08:00:27:8a:87:48',
@ -281,29 +282,13 @@ class InterfaceTestCase(base.FunctionalTest):
def _create_ethernet(self, ifname=None, networktype=None, ifclass=None,
datanetworks=None, host=None, expect_errors=False):
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):
if not ifclass and networktype in constants.PLATFORM_NETWORK_TYPES:
ifclass = constants.INTERFACE_CLASS_PLATFORM
for network_type in networktypelist:
network = self.dbapi.network_get_by_type(network_type)
networks.append(str(network.id))
elif ifclass == constants.INTERFACE_CLASS_PLATFORM and \
any(network_type not in constants.PLATFORM_NETWORK_TYPES
for network_type in networktypelist):
ifclass = networktype
if not ifclass and networktype:
ifclass = networktype
port_id = len(self.profile['ports'])
port = dbutils.create_test_ethernet_port(
id=port_id,
@ -317,22 +302,23 @@ class InterfaceTestCase(base.FunctionalTest):
if not networktype:
interface = dbutils.create_test_interface(ifname=ifname,
forihostid=host.id,
ihost_uuid=host.uuid,
networks=networks)
ihost_uuid=host.uuid)
interface_uuid = interface.uuid
else:
interface = dbutils.post_get_test_interface(
ifname=ifname,
ifclass=ifclass,
networktype=networktype,
networks=networks,
datanetworks=datanetworks,
forihostid=host.id, ihost_uuid=host.uuid)
response = self._post_and_check(interface, expect_errors)
if expect_errors is False:
interface_uuid = response.json['uuid']
interface['uuid'] = interface_uuid
if ifclass == constants.INTERFACE_CLASS_PLATFORM and networktype:
network = self.dbapi.network_get_by_type(networktype)
dbutils.create_test_interface_network(
interface_id=interface_uuid,
network_id=network.id)
self.profile['interfaces'].append(interface)
self.profile['ports'].append(port)
@ -341,11 +327,6 @@ class InterfaceTestCase(base.FunctionalTest):
def _create_bond(self, ifname, networktype=None, ifclass=None,
datanetworks=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)
@ -353,26 +334,13 @@ 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):
if not ifclass and networktype in constants.PLATFORM_NETWORK_TYPES:
ifclass = constants.INTERFACE_CLASS_PLATFORM
for network_type in networktypelist:
network = self.dbapi.network_get_by_type(network_type)
networks.append(str(network.id))
elif ifclass == constants.INTERFACE_CLASS_PLATFORM and \
any(network_type not in constants.PLATFORM_NETWORK_TYPES
for network_type in networktypelist):
ifclass = networktype
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',
datanetworks=datanetworks,
@ -403,42 +371,30 @@ class InterfaceTestCase(base.FunctionalTest):
def _create_vlan(self, ifname, networktype, ifclass, vlan_id,
lower_iface=None, datanetworks=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):
if not ifclass and networktype in constants.PLATFORM_NETWORK_TYPES:
ifclass = constants.INTERFACE_CLASS_PLATFORM
for network_type in networktypelist:
network = self.dbapi.network_get_by_type(network_type)
networks.append(str(network.id))
elif ifclass == constants.INTERFACE_CLASS_PLATFORM and \
any(network_type not in constants.PLATFORM_NETWORK_TYPES
for network_type in networktypelist):
ifclass = networktype
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']],
datanetworks=datanetworks,
forihostid=host.id, ihost_uuid=host.uuid)
self._post_and_check(interface, expect_errors)
response = self._post_and_check(interface, expect_errors)
if expect_errors is False:
if ifclass == constants.INTERFACE_CLASS_PLATFORM and networktype:
interface['uuid'] = response.json['uuid']
network = self.dbapi.network_get_by_type(networktype)
dbutils.create_test_interface_network(
interface_id=interface['uuid'],
network_id=network.id)
self.profile['interfaces'].append(interface)
return interface
@ -1131,7 +1087,6 @@ class TestPatch(InterfaceTestCase):
sriov_vf_driver='i40evf')
response = self.patch_dict_json(
'%s' % self._get_path(interface['uuid']),
networktype=constants.NETWORK_TYPE_PCI_SRIOV,
ifclass=constants.INTERFACE_CLASS_PCI_SRIOV,
sriov_numvfs=1,
sriov_vf_driver=vf_driver,
@ -1174,12 +1129,6 @@ class TestPost(InterfaceTestCase):
self._create_host(constants.WORKER, admin=constants.ADMIN_LOCKED)
self._create_datanetworks()
# Expected error: The oam network type is only supported on controller nodes
def test_invalid_oam_on_worker(self):
self._create_ethernet('oam', constants.NETWORK_TYPE_OAM,
constants.INTERFACE_CLASS_PLATFORM,
host=self.worker, 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):
@ -1237,8 +1186,6 @@ class TestPost(InterfaceTestCase):
ndict = dbutils.post_get_test_interface(
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,
@ -1251,7 +1198,6 @@ class TestPost(InterfaceTestCase):
ndict = dbutils.post_get_test_interface(
ihost_uuid=self.worker.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,
@ -1266,8 +1212,6 @@ class TestPost(InterfaceTestCase):
ndict = dbutils.post_get_test_interface(
ihost_uuid=self.controller.uuid,
ifname='name',
networktype=constants.NETWORK_TYPE_CLUSTER_HOST,
networks=['2'],
ifclass=constants.INTERFACE_CLASS_PLATFORM,
iftype=constants.INTERFACE_TYPE_ETHERNET,
ipv4_mode=constants.IPV4_DISABLED,
@ -1281,8 +1225,6 @@ class TestPost(InterfaceTestCase):
ndict = dbutils.post_get_test_interface(
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,
@ -1296,7 +1238,6 @@ 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,
@ -1308,8 +1249,6 @@ class TestPost(InterfaceTestCase):
ndict = dbutils.post_get_test_interface(
ihost_uuid=self.worker.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,
@ -1321,8 +1260,6 @@ class TestPost(InterfaceTestCase):
ndict = dbutils.post_get_test_interface(
ihost_uuid=self.worker.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,
@ -1335,8 +1272,6 @@ class TestPost(InterfaceTestCase):
ndict = dbutils.post_get_test_interface(
ihost_uuid=self.worker.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,
@ -1350,8 +1285,6 @@ class TestPost(InterfaceTestCase):
ndict = dbutils.post_get_test_interface(
ihost_uuid=self.worker.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,
@ -1367,7 +1300,6 @@ class TestPost(InterfaceTestCase):
ihost_uuid=self.worker.uuid,
datanetworks='group0-data0',
ifname='name',
networktype=constants.NETWORK_TYPE_DATA,
ifclass=constants.INTERFACE_CLASS_DATA,
iftype='AE',
aemode='active_standby',
@ -1381,7 +1313,6 @@ class TestPost(InterfaceTestCase):
ihost_uuid=self.worker.uuid,
datanetworks='group0-data0',
ifname='name',
networktype=constants.NETWORK_TYPE_DATA,
ifclass=constants.INTERFACE_CLASS_DATA,
iftype=constants.INTERFACE_TYPE_AE,
aemode='active_standby',
@ -1394,7 +1325,6 @@ class TestPost(InterfaceTestCase):
ndict = dbutils.post_get_test_interface(
ihost_uuid=self.worker.uuid,
ifname='name',
networktype=constants.NETWORK_TYPE_DATA,
ifclass=constants.INTERFACE_CLASS_DATA,
iftype=constants.INTERFACE_TYPE_AE,
aemode='balanced',
@ -1408,7 +1338,6 @@ class TestPost(InterfaceTestCase):
ihost_uuid=self.worker.uuid,
datanetworks='group0-data0',
ifname='name',
networktype=constants.NETWORK_TYPE_DATA,
ifclass=constants.INTERFACE_CLASS_DATA,
iftype=constants.INTERFACE_TYPE_AE,
aemode='802.3ad',
@ -1419,28 +1348,12 @@ class TestPost(InterfaceTestCase):
ihost_uuid=self.worker.uuid,
datanetworks='group0-data0',
ifname='name',
networktype=constants.NETWORK_TYPE_DATA,
ifclass=constants.INTERFACE_CLASS_DATA,
iftype=constants.INTERFACE_TYPE_AE,
aemode='balanced',
txhashpolicy=None)
self._post_and_check_failure(ndict)
# Expected error: Device interface with network type ___, and interface type
# 'aggregated ethernet' must be in mode '802.3ad'
def test_aemode_invalid_mgmt(self):
ndict = dbutils.post_get_test_interface(
ihost_uuid=self.worker.uuid,
datanetworks='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')
self._post_and_check_failure(ndict)
# Device interface with network type ___, and interface type
# 'aggregated ethernet' must be in mode 'active_standby' or 'balanced' or
# '802.3ad'.
@ -1449,57 +1362,26 @@ class TestPost(InterfaceTestCase):
ihost_uuid=self.worker.uuid,
datanetworks='group0-data0',
ifname='name',
networktype=constants.NETWORK_TYPE_DATA,
ifclass=constants.INTERFACE_CLASS_DATA,
iftype=constants.INTERFACE_TYPE_AE,
aemode='bad_aemode',
txhashpolicy='layer2')
self._post_and_check_failure(ndict)
def test_aemode_invalid_oam(self):
def test_aemode_invalid_platform(self):
ndict = dbutils.post_get_test_interface(
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')
self._post_and_check_failure(ndict)
def test_aemode_invalid_cluster_host(self):
ndict = dbutils.post_get_test_interface(
ihost_uuid=self.worker.uuid,
ifname='name',
networktype=constants.NETWORK_TYPE_CLUSTER_HOST,
networks=['2'],
ifclass=constants.INTERFACE_CLASS_PLATFORM,
iftype=constants.INTERFACE_TYPE_AE,
aemode='bad_aemode',
txhashpolicy='layer2')
self._post_and_check_failure(ndict)
# Expected error: Interface ___ does not have associated cluster-host
# interface on controller.
def test_no_cluster_host_on_controller(self):
ndict = dbutils.post_get_test_interface(
ihost_uuid=self.worker.uuid,
ifname='name',
networktype=constants.NETWORK_TYPE_CLUSTER_HOST,
networks=['2'],
ifclass=constants.INTERFACE_CLASS_PLATFORM,
iftype=constants.INTERFACE_TYPE_ETHERNET,
aemode='balanced',
txhashpolicy='layer2')
self._post_and_check_failure(ndict)
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)
@ -1509,8 +1391,6 @@ class TestPost(InterfaceTestCase):
ndict = dbutils.post_get_test_interface(
ihost_uuid=self.controller.uuid,
ifname='cluster0',
networktype=constants.NETWORK_TYPE_CLUSTER_HOST,
networks=['2'],
ifclass=constants.INTERFACE_CLASS_PLATFORM,
iftype=constants.INTERFACE_TYPE_ETHERNET,
imtu=1600)
@ -1529,7 +1409,6 @@ class TestPost(InterfaceTestCase):
ihost_uuid=self.worker.uuid,
datanetworks='group0-ext1',
ifname='bond1',
networktype=constants.NETWORK_TYPE_DATA,
ifclass=constants.INTERFACE_CLASS_DATA,
iftype=constants.INTERFACE_TYPE_AE,
aemode='balanced',
@ -1559,7 +1438,6 @@ class TestPost(InterfaceTestCase):
ihost_uuid=self.worker.uuid,
datanetworks='group0-ext1',
ifname='bond0',
networktype=constants.NETWORK_TYPE_DATA,
ifclass=constants.INTERFACE_CLASS_DATA,
iftype=constants.INTERFACE_TYPE_AE,
aemode='balanced',
@ -1579,7 +1457,6 @@ class TestPost(InterfaceTestCase):
ihost_uuid=self.worker.uuid,
datanetworks='group0-ext1',
ifname='bond1',
networktype=constants.NETWORK_TYPE_DATA,
ifclass=constants.INTERFACE_CLASS_DATA,
iftype=constants.INTERFACE_TYPE_VLAN,
aemode='balanced',
@ -1658,7 +1535,9 @@ class TestPost(InterfaceTestCase):
def test_create_invalid_oam_data_ethernet(self):
self._create_ethernet('shared',
networktype=constants.NETWORK_TYPE_DATA,
ifclass=constants.INTERFACE_CLASS_PLATFORM,
ifclass=constants.INTERFACE_CLASS_DATA,
datanetworks='group0-data0',
host=self.controller,
expect_errors=True)
# Expected message:
@ -1715,13 +1594,6 @@ class TestCpePost(InterfaceTestCase):
lower_iface=iface, datanetworks='group0-ext1',
expect_errors=True)
# Expected message: An interface with \'oam\' network type is already
# provisioned on this node
def test_create_invalid_duplicate_networktype(self):
self._create_ethernet('oam', constants.NETWORK_TYPE_OAM)
self._create_ethernet('bad', constants.NETWORK_TYPE_OAM,
expect_errors=True)
# 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)
@ -1733,13 +1605,6 @@ class TestCpePost(InterfaceTestCase):
lower_iface=iface, datanetworks='group0-ext1',
expect_errors=True)
# Expected message: VLAN interfaces cannot have an interface class 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
# assigned to a VLAN interface
def test_create_invalid_vlan_with_vlan_data_network(self):
@ -1775,12 +1640,6 @@ class TestCpePost(InterfaceTestCase):
mock.ANY, mock.ANY, vlans=mock.ANY, test=mock.ANY)
mock_iinterface_destroy.assert_called_once_with(mock.ANY)
# Expected error: At least one provider network must be selected.
def test_create_invalid_no_data_network(self):
self._create_ethernet('data',
networktype=constants.NETWORK_TYPE_DATA,
expect_errors=True)
# Expected error: Data interface data0 is already attached to this
# Data Network: group0-data0.
def test_create_invalid_data_network_used(self):
@ -1819,13 +1678,6 @@ class TestCpePatch(InterfaceTestCase):
admin=constants.ADMIN_LOCKED)
self._create_datanetworks()
def test_create_invalid_cluster_host_data_ethernet(self):
self._create_ethernet('shared',
networktype=[constants.NETWORK_TYPE_CLUSTER_HOST,
constants.NETWORK_TYPE_DATA],
datanetworks='group0-data0',
expect_errors=True)
@testtools.skip("deprecate neutron bind interface")
@mock.patch.object(rpcapi.ConductorAPI, 'neutron_bind_interface')
def test_patch_neutron_bind_failed(self, mock_neutron_bind_interface):
@ -1853,23 +1705,11 @@ class TestCpePatch(InterfaceTestCase):
constants.NETWORK_TYPE_NONE)
response = self.patch_dict_json(
'%s' % self._get_path(interface['uuid']),
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)
# Expected error: At most one port must be enabled.
def test_invalid_sriov_no_port(self):
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,
ifclass=constants.INTERFACE_CLASS_DATA,
expect_errors=True)
self.assertEqual(http_client.BAD_REQUEST, response.status_int)
self.assertEqual('application/json', response.content_type)
# Expected error: SR-IOV can't be configured on this interface
def test_invalid_sriov_totalvfs_zero(self):
interface = dbutils.create_test_interface(forihostid='1')
@ -1878,7 +1718,6 @@ 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,
ifclass=constants.INTERFACE_CLASS_PCI_SRIOV,
sriov_numvfs=1,
expect_errors=True)

View File

@ -7,8 +7,10 @@
# SPDX-License-Identifier: Apache-2.0
#
import mock
from six.moves import http_client
from sysinv.api.controllers.v1 import interface as api_if_v1
from sysinv.common import constants
from sysinv.tests.api import base
from sysinv.tests.db import utils as dbutils
@ -17,6 +19,13 @@ from sysinv.tests.db import utils as dbutils
class InterfaceNetworkTestCase(base.FunctionalTest):
def setUp(self):
super(InterfaceNetworkTestCase, self).setUp()
p = mock.patch.object(api_if_v1, '_get_lower_interface_macs')
self.mock_lower_macs = p.start()
self.mock_lower_macs.return_value = {'enp0s18': '08:00:27:8a:87:48',
'enp0s19': '08:00:27:ea:93:8e'}
self.addCleanup(p.stop)
self.system = dbutils.create_test_isystem()
self.load = dbutils.create_test_load()
self.controller = dbutils.create_test_ihost(
@ -76,6 +85,12 @@ class InterfaceNetworkTestCase(base.FunctionalTest):
name='oam',
type=constants.NETWORK_TYPE_OAM,
address_pool_id=self.address_pool_oam.id)
self.oam_address = dbutils.create_test_address(
family=2,
address='10.10.10.3',
prefix=24,
name='controller-0-oam',
address_pool_id=self.address_pool_oam.id)
self.address_pool_pxeboot = dbutils.create_test_address_pool(
id=4,
network='192.168.202.0',
@ -86,6 +101,12 @@ class InterfaceNetworkTestCase(base.FunctionalTest):
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',
prefix=24,
name='controller-0-pxeboot',
address_pool_id=self.address_pool_pxeboot.id)
def _post_and_check(self, ndict, expect_errors=False):
response = self.post_json('%s' % self._get_path(), ndict,
@ -162,7 +183,7 @@ class InterfaceNetworkCreateTestCase(InterfaceNetworkTestCase):
worker_interface_network = dbutils.post_get_test_interface_network(
interface_uuid=worker_interface.uuid,
network_uuid=self.oam_network.uuid)
self._post_and_check(worker_interface_network, expect_errors=False)
self._post_and_check(worker_interface_network, expect_errors=True)
def test_create_pxeboot_interface_network(self):
controller_interface = dbutils.create_test_interface(
@ -290,3 +311,68 @@ class InterfaceNetworkCreateTestCase(InterfaceNetworkTestCase):
interface_uuid=worker_interface.uuid,
network_uuid=self.mgmt_network.uuid)
self._post_and_check(worker_interface_network, expect_errors=True)
# Expected error: The oam network type is only supported on controller nodes
def test_invalid_oam_on_worker(self):
worker_interface = dbutils.create_test_interface(
ifname='enp0s3',
forihostid=self.worker.id)
worker_interface_network = dbutils.post_get_test_interface_network(
interface_uuid=worker_interface.uuid,
network_uuid=self.oam_network.uuid)
self._post_and_check(worker_interface_network, expect_errors=True)
# Expected message: An interface with \'oam\' network type is already
# provisioned on this node
def test_create_invalid_duplicate_networktype(self):
controller_interface1 = dbutils.create_test_interface(
ifname='enp0s3',
forihostid=self.controller.id)
dbutils.create_test_interface_network(
interface_id=controller_interface1.id,
network_id=self.oam_network.id)
controller_interface2 = dbutils.create_test_interface(
ifname='enp0s8',
forihostid=self.controller.id)
controller_interface_network = dbutils.post_get_test_interface_network(
interface_uuid=controller_interface2.uuid,
network_uuid=self.oam_network.uuid)
self._post_and_check(controller_interface_network, expect_errors=True)
# Expected error: Interface ___ does not have associated cluster-host
# interface on controller.
def test_no_cluster_host_on_controller(self):
worker_interface = dbutils.create_test_interface(
ifname='enp0s3',
forihostid=self.worker.id)
worker_interface_network = dbutils.post_get_test_interface_network(
interface_uuid=worker_interface.uuid,
network_uuid=self.cluster_host_network.uuid)
self._post_and_check(worker_interface_network, expect_errors=True)
# Expected error: An interface with interface class data cannot
# assign platform networks.
def test_create_invalid_network_on_data_interface(self):
controller_interface = dbutils.create_test_interface(
ifname='enp0s3',
ifclass=constants.NETWORK_TYPE_DATA,
forihostid=self.controller.id)
controller_interface_network = dbutils.post_get_test_interface_network(
interface_uuid=controller_interface.uuid,
network_uuid=self.cluster_host_network.uuid)
self._post_and_check(controller_interface_network, expect_errors=True)
# Expected error: Device interface with network type ___, and interface type
# 'aggregated ethernet' must be in mode '802.3ad'
def test_aemode_invalid_mgmt(self):
controller_interface = dbutils.create_test_interface(
ifname='name',
forihostid=self.controller.id,
ifclass=constants.INTERFACE_CLASS_PLATFORM,
iftype=constants.INTERFACE_TYPE_AE,
aemode='balanced',
txhashpolicy='layer2')
controller_interface_network = dbutils.post_get_test_interface_network(
interface_uuid=controller_interface.uuid,
network_uuid=self.mgmt_network.uuid)
self._post_and_check(controller_interface_network, expect_errors=True)

View File

@ -674,8 +674,6 @@ def post_get_test_interface(**kw):
'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'),
'datanetworks': datanetworks_list,
@ -710,8 +708,7 @@ def get_test_interface(**kw):
'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', []),
'networktypelist': kw.get('networktypelist', []),
'aemode': kw.get('aemode'),
'txhashpolicy': kw.get('txhashpolicy', None),
'datanetworks': datanetworks_list,
@ -737,6 +734,7 @@ def create_test_interface(**kw):
interface = get_test_interface(**kw)
datanetworks_list = interface.get('datanetworks') or []
networks_list = interface.get('networks') or []
# Let DB generate ID if it isn't specified explicitly
if 'id' not in kw:
@ -745,10 +743,22 @@ def create_test_interface(**kw):
if 'datanetworks' in interface:
del interface['datanetworks']
if 'networks' in interface:
del interface['networks']
dbapi = db_api.get_instance()
forihostid = kw.get('forihostid')
interface_obj = dbapi.iinterface_create(forihostid, interface)
# assign the network to the interface
for network in networks_list:
if not network:
continue
net = dbapi.network_get(network)
values = {'interface_id': interface_obj.id,
'network_id': net.id}
dbapi.interface_network_create(values)
# assign the interface to the datanetwork
for datanetwork in datanetworks_list:
if not datanetwork:

View File

@ -64,20 +64,21 @@ class BaseTestCase(dbbase.DbTestCase):
super(BaseTestCase, self).assertEqual(expected, observed, message)
def _setup_address_and_routes(self, iface):
networktype = utils.get_primary_network_type(iface)
if networktype in NETWORKTYPES_WITH_V4_ADDRESSES:
if not iface['ifclass'] or iface['ifclass'] == constants.INTERFACE_CLASS_NONE:
return None
if iface['ifclass'] == constants.INTERFACE_CLASS_PLATFORM:
address = {'interface_id': iface['id'],
'family': 4,
'prefix': 24,
'address': '192.168.1.2'}
self.addresses.append(dbutils.create_test_address(**address))
elif networktype in NETWORKTYPES_WITH_V6_ADDRESSES:
elif iface['ifclass'] == constants.INTERFACE_CLASS_DATA:
address = {'interface_id': iface['id'],
'family': 6,
'prefix': 64,
'address': '2001:1::2'}
self.addresses.append(dbutils.create_test_address(**address))
if networktype in NETWORKTYPES_WITH_V4_ROUTES:
if iface['ifclass'] == constants.INTERFACE_CLASS_DATA:
route = {'interface_id': iface['id'],
'family': 4,
'prefix': 24,
@ -92,7 +93,7 @@ class BaseTestCase(dbbase.DbTestCase):
'gateway': '192.168.1.1',
'metric': '1'}
self.routes.append(dbutils.create_test_route(**route))
if networktype in NETWORKTYPES_WITH_V6_ROUTES:
if iface['ifclass'] == constants.INTERFACE_CLASS_DATA:
route = {'interface_id': iface['id'],
'family': 6,
'prefix': 64,