Merge "Remove datanetworks param from interface commands"

This commit is contained in:
Zuul 2019-06-27 18:45:25 +00:00 committed by Gerrit Code Review
commit 87ceb15d6d
9 changed files with 216 additions and 397 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."
"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."
"sriov_numvfs (Optional)", "plain", "xsd:integer", "The number of VFs configured on the interfaces port; only applicable if ``ifclass : pci-sriov`` where only a single port is associated with the interface."
@ -2446,7 +2445,6 @@ itemNotFound (404)
"vlan_id": null,
"imtu": 1500,
"aemode": null,
"datanetworks": [],
"ifclass": "platform"
"ifname": "eth1"
},
@ -2478,7 +2476,6 @@ itemNotFound (404)
],
"aemode": "balanced",
"datanetworks": ["physnet-0,physnet-1"],
"ifclass": "data"
"ifname": "data1"
}
@ -2523,7 +2520,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."
"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."
"sriov_numvfs (Optional)", "plain", "xsd:integer", "The number of VFs configured on the interfaces port; only applicable if ``ifclass : pci-sriov`` where only a single port is associated with the interface."
@ -2552,7 +2548,6 @@ itemNotFound (404)
"href" : "http://10.10.10.2:6385/iinterfaces/740a5bec-b7a8-4645-93ed-aea0d4cfbf86/ports"
}
],
"datanetworks" : ["physnet-0,physnet-1"],
"txhashpolicy" : "layer2",
"schedpolicy" : null,
"uuid" : "740a5bec-b7a8-4645-93ed-aea0d4cfbf86",
@ -2617,7 +2612,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."
"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."
"used_by (Optional)", "plain", "xsd:list", "This attribute specifies a comma-separated list of interfaces that use this interface."
@ -2637,7 +2631,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."
"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."
"sriov_numvfs (Optional)", "plain", "xsd:integer", "The number of VFs configured on the interfaces port; only applicable if ``ifclass : pci-sriov`` where only a single port is associated with the interface."
@ -2660,7 +2653,6 @@ badMediaType (415)
"txhashpolicy": "layer2",
"ihost_uuid": "ff453a51-1d3b-437f-a65e-b2d163f79f85",
"imtu": "1500",
"datanetworks": "physnet-0,physnet1",
"ifclass": "data",
"ifname": "data1",
"uses": ['eth2','eth3'],
@ -2714,7 +2706,6 @@ badMediaType (415)
],
"aemode": "balanced",
"sriov_numvfs": 0,
"datanetworks": ["physnet-0,physnet-1"],
"ifclass": "data",
"ifname": "data1",
"ports": null,
@ -2748,7 +2739,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."
"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."
"used_by (Optional)", "plain", "xsd:list", "This attribute specifies a comma-separated list of interfaces that use this interface."
@ -2767,7 +2757,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."
"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."
"sriov_numvfs (Optional)", "plain", "xsd:integer", "The number of VFs configured on the interfaces port; only applicable if ``ifclass : pci-sriov`` where only a single port is associated with the interface."
@ -2796,11 +2785,6 @@ badMediaType (415)
"value": "layer2",
"op": "replace"
},
{
"path": "/datanetworks",
"value": "physnet-0,physnet-1",
"op": "replace"
},
{
"path": "/aemode",
"value": "active_standby",
@ -2859,7 +2843,6 @@ badMediaType (415)
],
"aemode": "active_standby",
"datanetworks": ["physnet-0,physnet-1"],
"ifclass": "data",
"ifname": "data1",
"ports": null

View File

@ -16,7 +16,7 @@ from cgtsclient.v1 import iinterface as iinterface_utils
def _print_iinterface_show(cc, iinterface):
fields = ['ifname', 'iftype', 'ports', 'datanetworks',
fields = ['ifname', 'iftype', 'ports',
'imac', 'imtu', 'ifclass',
'aemode', 'schedpolicy', 'txhashpolicy',
'uuid', 'ihost_uuid',
@ -88,9 +88,9 @@ def do_host_if_list(cc, args):
setattr(i, 'attrs', attr_str)
field_labels = ['uuid', 'name', 'class', 'type', 'vlan id', 'ports',
'uses i/f', 'used by i/f', 'attributes', 'data networks']
'uses i/f', 'used by i/f', 'attributes']
fields = ['uuid', 'ifname', 'ifclass', 'iftype', 'vlan_id', 'ports',
'uses', 'used_by', 'attrs', 'datanetworks']
'uses', 'used_by', 'attrs']
utils.print_list(
iinterfaces, fields, field_labels, sortby=0, no_wrap_fields=['ports'])
@ -120,13 +120,6 @@ def do_host_if_delete(cc, args):
choices=['ae', 'vlan', 'virtual'],
nargs='?',
help="Type of the interface")
@utils.arg('datanetworks',
metavar='<datanetworks>',
nargs='?',
default=None,
help=('The data network attached to the interface '
'(default: %(default)s) '
'[REQUIRED when interface class is data or pci-passthrough'))
@utils.arg('-a', '--aemode',
metavar='<ae mode>',
choices=['balanced', 'active_standby', '802.3ad'],
@ -167,7 +160,7 @@ def do_host_if_add(cc, args):
"""Add an interface."""
field_list = ['ifname', 'iftype', 'imtu', 'ifclass', 'aemode',
'txhashpolicy', 'datanetworks', 'vlan_id',
'txhashpolicy', 'vlan_id',
'ipv4_mode', 'ipv6_mode', 'ipv4_pool', 'ipv6_pool']
ihost = ihost_utils._find_ihost(cc, args.hostnameorid)
@ -189,10 +182,6 @@ def do_host_if_add(cc, args):
user_specified_fields = dict((k, v) for (k, v) in vars(args).items()
if k in field_list and not (v is None))
if 'datanetworks' in user_specified_fields.keys():
user_specified_fields['datanetworks'] = \
user_specified_fields['datanetworks'].split(',')
user_specified_fields['ihost_uuid'] = ihost.uuid
user_specified_fields['ports'] = portnamesoruuids
user_specified_fields['uses'] = uses
@ -219,12 +208,6 @@ def do_host_if_add(cc, args):
@utils.arg('-m', '--imtu',
metavar='<mtu>',
help='The MTU of the interface')
@utils.arg('-p', '--providernetworks',
metavar='<providernetworks>',
help='[DEPRECATED] The provider network attached to the interface')
@utils.arg('-d', '--datanetworks',
metavar='<datanetworks>',
help='The data network attached to the interface')
@utils.arg('-a', '--aemode',
metavar='<ae mode>',
choices=['balanced', 'active_standby', '802.3ad'],
@ -263,7 +246,7 @@ def do_host_if_modify(cc, args):
"""Modify interface attributes."""
rwfields = ['iftype', 'ifname', 'imtu', 'aemode', 'txhashpolicy',
'datanetworks', 'providernetworks', 'ports', 'ifclass',
'ports', 'ifclass',
'ipv4_mode', 'ipv6_mode', 'ipv4_pool', 'ipv6_pool',
'sriov_numvfs', 'sriov_vf_driver']
@ -272,15 +255,6 @@ def do_host_if_modify(cc, args):
user_specified_fields = dict((k, v) for (k, v) in vars(args).items()
if k in rwfields and not (v is None))
if 'providernetworks' in user_specified_fields.keys():
user_specified_fields['datanetworks'] = \
user_specified_fields['providernetworks']
del user_specified_fields['providernetworks']
elif 'datanetworks' in user_specified_fields.keys():
user_specified_fields['datanetworks'] = \
user_specified_fields['datanetworks']
interface = _find_interface(cc, ihost, args.ifnameoruuid)
fields = interface.__dict__
fields.update(user_specified_fields)
@ -294,8 +268,6 @@ def do_host_if_modify(cc, args):
for p in interface.ports:
user_specified_fields['ifname'] = p
break
if interface.ifclass == 'data':
user_specified_fields['datanetworks'] = 'none'
patch = []
for (k, v) in user_specified_fields.items():

View File

@ -56,3 +56,11 @@ class InterfaceDataNetworkManager(base.Manager):
def remove(self, interface_datanetwork_uuid):
path = '/v1/interface_datanetworks/%s' % interface_datanetwork_uuid
return self._delete(path)
def get_datanetwork_names(cc, interface):
datanetwork_names = []
ifdns = cc.interface_datanetwork.list_by_interface(interface.uuid)
for ifdn in ifdns:
datanetwork_names.append(getattr(ifdn, 'datanetwork_name'))
return datanetwork_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_datanetwork as ifdn_utils
from cgtsclient.v1 import interface_network as ifnet_utils
from cgtsclient.v1 import iprofile as iprofile_utils
import math
@ -62,11 +63,12 @@ def get_portconfig(iprofile):
def get_interfaceconfig(cc, iprofile):
istr = ''
for interface in iprofile.interfaces:
istr = istr + "%s: " % (interface.ifname)
if interface.ifclass == 'platform':
network_names = ifnet_utils.get_network_names(cc, interface)
istr = istr + "%s: %s" % (interface.ifname, network_names)
istr = istr + "( %s )" % network_names
elif interface.ifclass == 'data':
istr = istr + "( %s )" % interface.datanetworks
istr = istr + "( %s )" % ifdn_utils.get_datanetwork_names(cc, interface)
_get_interface_ports_interfaces(iprofile, interface)
if interface.ports:
istr = istr + " | %s | PORTS = %s" % (interface.iftype, interface.ports)

View File

@ -145,9 +145,6 @@ class Interface(base.APIBase):
txhashpolicy = wtypes.text
"Represent the txhashpolicy of the interface"
datanetworks = [wtypes.text]
"Represent the datanetworks of the interface"
ifcapabilities = {wtypes.text: utils.ValidTypes(wtypes.text,
six.integer_types)}
"This interface's meta data"
@ -209,7 +206,6 @@ class Interface(base.APIBase):
# interface = iinterface.from_rpc_object(rpc_interface, fields)
kwargs = rpc_interface.as_dict()
datanetworks_list = kwargs.pop('datanetworks')
interface = Interface(**kwargs)
if not expand:
@ -219,8 +215,7 @@ class Interface(base.APIBase):
'aemode', 'schedpolicy', 'txhashpolicy',
'vlan_id', 'uses', 'usesmodify', 'used_by',
'ipv4_mode', 'ipv6_mode', 'ipv4_pool', 'ipv6_pool',
'sriov_numvfs', 'sriov_vf_driver',
'datanetworks'])
'sriov_numvfs', 'sriov_vf_driver'])
# never expose the ihost_id attribute
interface.ihost_id = wtypes.Unset
@ -261,13 +256,6 @@ class Interface(base.APIBase):
if interface.ipv6_mode != constants.IPV6_POOL:
interface.ipv6_pool = wtypes.Unset
datanetworks_names_list = []
for dn in datanetworks_list:
dn = pecan.request.dbapi.datanetwork_get(dn)
datanetworks_names_list.append(dn.name)
interface.datanetworks = datanetworks_names_list
return interface
@ -430,9 +418,6 @@ class InterfaceController(rest.RestController):
uses = None
ports = None
datanetworks = []
datanetworks_to_add = []
interface_datanetworks_to_remove = []
patches_to_remove = []
for p in patch:
if '/ifclass' == p['path']:
@ -444,15 +429,6 @@ class InterfaceController(rest.RestController):
elif '/ports' == p['path']:
ports = p['value']
patches_to_remove.append(p)
elif '/datanetworks' == p['path']:
datanetworks = p['value'].split(',')
patches_to_remove.append(p)
elif '/datanetworks_to_add' == p['path']:
datanetworks_to_add = p['value'].split(',')
patches_to_remove.append(p)
elif '/interface_datanetworks_to_remove' == p['path']:
interface_datanetworks_to_remove = p['value'].split(',')
patches_to_remove.append(p)
if uses:
patch.append(dict(path='/uses', value=uses, op='replace'))
@ -519,7 +495,6 @@ class InterfaceController(rest.RestController):
# Process updates
vlan_id = None
delete_addressing = False
delete_ifdn = False
for p in patch:
if '/vlan_id' in p['path']:
@ -560,7 +535,6 @@ class InterfaceController(rest.RestController):
interface['ipv4_mode'] = None
interface['ipv6_mode'] = None
delete_addressing = True
delete_ifdn = True
else:
# Otherwise make sure that appropriate defaults are set.
interface = _set_defaults(interface)
@ -573,8 +547,7 @@ class InterfaceController(rest.RestController):
interface = _check("modify", interface,
ports=ports, ifaces=uses,
existing_interface=rpc_interface.as_dict(),
datanetworks=datanetworks)
existing_interface=rpc_interface.as_dict())
if uses:
# Update MAC address if uses list changed
@ -610,40 +583,6 @@ class InterfaceController(rest.RestController):
if _is_ipv6_address_mode_updated(interface, rpc_interface):
_update_ipv6_address_mode(interface)
# Update interface-datanetworks
if datanetworks_to_add:
for datanetwork_id in datanetworks_to_add:
values = {'interface_id': interface['id'],
'datanetwork_id': datanetwork_id}
try:
pecan.request.dbapi.interface_datanetwork_create(values)
except exception.InterfaceDataNetworkAlreadyExists:
pass
elif datanetworks:
_update_interface_datanetworks(
ihost['uuid'], interface, datanetworks, delete_ifdn)
try:
# Remove old datanetworks from the interface
if interface_datanetworks_to_remove:
for ifdatanet_id in interface_datanetworks_to_remove:
pecan.request.dbapi.interface_datanetwork_destroy(
ifdatanet_id)
elif (orig_ifclass == constants.INTERFACE_CLASS_DATA and
(not ifclass or
ifclass != constants.INTERFACE_CLASS_DATA)):
# data networks apply only for DATA
ifdatanets = \
pecan.request.dbapi.interface_datanetwork_get_by_interface(
rpc_interface['uuid'])
for ifdatanet in ifdatanets:
pecan.request.dbapi.interface_datanetwork_destroy(ifdatanet.uuid)
except Exception as e:
LOG.exception(e)
msg = _("Failed to remove interface datanetwork association for "
"interface %s" % (interface['ifname']))
raise wsme.exc.ClientSideError(msg)
# Commit operation with neutron
if (interface['ifclass'] and
interface['ifclass'] in NEUTRON_INTERFACE_CLASS):
@ -719,65 +658,6 @@ class InterfaceController(rest.RestController):
# UTILS
##############
def _update_interface_datanetworks(host_uuid, interface,
datanetworks=None,
delete_ifdn=False):
pns = []
if datanetworks:
# remove 'none' from datanetworks
datanetworks = \
[x for x in datanetworks if x != constants.DATANETWORK_TYPE_NONE]
for datanetwork_id in datanetworks:
dn = pecan.request.dbapi.datanetwork_get(datanetwork_id)
pns.append(dn.name)
elif 'datanetworks' in interface:
pns = interface['datanetworks']
LOG.info("_update_interface_datanetworks interface=%s datanetworks=%s pns=%s" %
(interface, datanetworks, pns))
# remove from the interface datanetworks not in list
ifdns = \
pecan.request.dbapi.interface_datanetwork_get_by_host(
host_uuid)
for ifdn in ifdns:
# if this is not this interface, continue
if_uuid = interface.get('uuid', None)
if if_uuid:
if if_uuid != ifdn.interface_uuid:
continue
elif ifdn.ifname != interface.get('ifname'):
continue
LOG.debug("_update_interface_datanetworks host_uuid %s "
"interface=%s ifdn=%s" %
(host_uuid, interface, ifdn.as_dict()))
if (pns and ifdn.datanetwork_name not in pns) or delete_ifdn:
LOG.info("interface_datanetwork_destroy %s %s delete_ifdn=%s" %
(ifdn.uuid, ifdn.ifname, delete_ifdn))
pecan.request.dbapi.interface_datanetwork_destroy(
ifdn.uuid)
for pn in pns:
dn = pecan.request.dbapi.datanetwork_get(pn)
values = {'interface_id': interface['id'],
'datanetwork_id': dn.id}
try:
ifdn = pecan.request.dbapi.interface_datanetwork_create(values)
except exception.InterfaceDataNetworkAlreadyExists:
pass
except Exception as e:
LOG.exception(e)
msg = _("Failed to create interface datanetwork "
"assignment for interface %s" %
(interface['ifname']))
raise wsme.exc.ClientSideError(msg)
return ifdns
def _dynamic_address_allocation():
mgmt_network = pecan.request.dbapi.network_get_by_type(
constants.NETWORK_TYPE_MGMT)
@ -1139,131 +1019,6 @@ def _check_network_type_and_port(interface, ihost,
raise wsme.exc.ClientSideError(msg)
def _check_datanetworks(ihost,
interface,
interface_list,
existing_interface,
datanetworks=None):
if 'id' in interface:
this_interface_id = interface['id']
else:
this_interface_id = 0
ifclass = interface['ifclass']
iftype = interface['iftype']
if not datanetworks:
datanetworks = interface.get('datanetworks') or []
# remove 'none' from datanetworks
datanetworks = \
[x for x in datanetworks if x != constants.DATANETWORK_TYPE_NONE]
LOG.debug("_check_datanetworks datanetworks interface=%s datanetworks=%s" %
(interface, datanetworks))
# Get all provisioned datanetworks
all_datanetworks = {}
db_datanetworks = pecan.request.dbapi.datanetworks_get_all()
for db in db_datanetworks:
all_datanetworks[db.name] = {
'network_type': db.network_type}
# Ensure a valid datanetwork is specified
# Ensure at least one datanetwork is selected for 'data',
# and none for 'oam', 'mgmt' and 'cluster-host'
# Ensure uniqueness of the datanetworks
datanetworks_list = []
for datanetwork in datanetworks:
if datanetwork == constants.DATANETWORK_TYPE_NONE:
continue
dn = pecan.request.dbapi.datanetwork_get(datanetwork)
datanetworks_list.append(dn.name)
if interface['ifclass'] in NEUTRON_INTERFACE_CLASS:
if len(datanetworks) > MAX_DATANETWORK_LEN:
msg = _("Data network list must not exceed %d characters." %
MAX_DATANETWORK_LEN)
raise wsme.exc.ClientSideError(msg)
for pn in [n.strip() for n in datanetworks_list]:
if pn not in all_datanetworks.keys():
msg = _("Data network '%s' does not exist." % pn)
raise wsme.exc.ClientSideError(msg)
if datanetworks_list.count(pn) > 1:
msg = (_("Specifying duplicate data network '%(name)s' "
"is not permitted") % {'name': pn})
raise wsme.exc.ClientSideError(msg)
datanet = all_datanetworks[pn]
if iftype == constants.INTERFACE_TYPE_VLAN:
if datanet['network_type'] == \
constants.DATANETWORK_TYPE_VLAN:
msg = _("VLAN based data network '%s' cannot be "
"assigned to a VLAN interface" % pn)
raise wsme.exc.ClientSideError(msg)
# If pxeboot, Mgmt network types are consolidated
# with a data network type on the same interface,
# in which case, they would be the primary network
# type. Ensure that the only data type that
# can be assigned is VLAN.
if (datanet['network_type'] != constants.DATANETWORK_TYPE_VLAN and
ifclass not in NEUTRON_NETWORK_TYPES):
msg = _("Data network '%s' of type '%s' cannot be assigned "
"to an interface with interface class '%s'"
% (pn, datanet['network_type'], ifclass))
raise wsme.exc.ClientSideError(msg)
# This ensures that a specific data network type can
# only be assigned to 1 data interface. Such as the case of
# when only 1 vxlan data is required when SDN is enabled
if interface['ifclass'] == constants.INTERFACE_CLASS_DATA and interface_list:
for pn in [n.strip() for n in datanetworks_list]:
for i in interface_list:
if i.id == this_interface_id:
continue
if not i.ifclass or not i.datanetworks:
continue
if constants.NETWORK_TYPE_DATA != i.ifclass:
continue
other_datanetworks = []
for datanetwork in i.datanetworks:
dn = pecan.request.dbapi.datanetwork_get(datanetwork)
other_datanetworks.append(dn.name)
if pn in other_datanetworks:
msg = _("Data interface %(ifname)s is already "
"attached to this Data Network: "
"%(datanetwork)s." %
{'ifname': i.ifname, 'datanetwork': pn})
raise wsme.exc.ClientSideError(msg)
elif (not _neutron_providernet_extension_supported() and
interface['ifclass'] in PCI_INTERFACE_CLASS):
# When the neutron implementation is not our own and it does not
# support our data network extension we still want to do minimal
# validation of the data network list but we cannot do more
# complex validation because we do not have any additional information
# about the data networks.
if not datanetworks:
msg = _("At least one data network must be selected.")
raise wsme.exc.ClientSideError(msg)
elif (interface['ifclass'] and
interface['ifclass'] not in NEUTRON_INTERFACE_CLASS and
not existing_interface):
if datanetworks:
msg = _("Data network(s) not supported "
"for non-data interfaces. (%s) (%s)" %
(interface['ifclass'], str(existing_interface)))
raise wsme.exc.ClientSideError(msg)
elif (_neutron_providernet_extension_supported() or
interface['ifclass'] not in NEUTRON_INTERFACE_CLASS):
interface['datanetworks'] = None
def _check_interface_data(op, interface, ihost, existing_interface,
datanetworks=None):
# Get data
@ -1439,13 +1194,6 @@ def _check_interface_data(op, interface, ihost, existing_interface,
interface_port,
host_port)
# Check datanetworks (formerly known as providernetworks)
_check_datanetworks(ihost,
interface,
interface_list,
existing_interface,
datanetworks)
# check MTU
if interface['iftype'] == constants.INTERFACE_TYPE_VLAN:
vlan_mtu = interface['imtu']
@ -1972,8 +1720,6 @@ def _create(interface, from_profile=False):
else:
forihostid = ihostId
datanetworks = interface.get('datanetworks')
LOG.debug("iinterface post interfaces ihostid: %s" % forihostid)
interface.update({'forihostid': ihost['id'],
@ -2027,9 +1773,6 @@ def _create(interface, from_profile=False):
forihostid,
interface)
# Create interface-datanetworks
_update_interface_datanetworks(ihost['uuid'], new_interface, datanetworks)
try:
# Add extended attributes stored in other tables
_add_extended_attributes(ihost['uuid'], new_interface, interface)

View File

@ -147,6 +147,8 @@ class InterfaceDataNetworkController(rest.RestController):
self._check_interface_class(interface_obj)
self._check_interface_mtu(interface_obj, datanetwork_obj)
self._check_duplicate_interface_datanetwork(interface_datanetwork_dict)
self._check_iftype_network_type(interface_obj, datanetwork_obj)
self._check_datanetwork_used(interface_obj, datanetwork_obj)
result = pecan.request.dbapi.interface_datanetwork_create(
interface_datanetwork_dict)
@ -240,15 +242,35 @@ class InterfaceDataNetworkController(rest.RestController):
return result
def _check_duplicate_interface_datanetwork(self, interface_datanetwork):
result = self._query_interface_datanetwork(interface_datanetwork)
if not result:
ifdn = self._query_interface_datanetwork(interface_datanetwork)
if not ifdn:
return
msg = _("Interface '%s' assignment with Data Network '%s' "
"already exists."
% (interface_datanetwork['interface_id'],
interface_datanetwork['datanetwork_id']))
% (ifdn['ifname'],
ifdn['datanetwork_name']))
raise wsme.exc.ClientSideError(msg)
@staticmethod
def _check_iftype_network_type(interface_obj, datanetwork_obj):
if interface_obj.iftype == constants.INTERFACE_TYPE_VLAN:
if datanetwork_obj.network_type == constants.DATANETWORK_TYPE_VLAN:
msg = _("VLAN based data network '%s' cannot be "
"assigned to a VLAN interface" % datanetwork_obj.name)
raise wsme.exc.ClientSideError(msg)
@staticmethod
def _check_datanetwork_used(interface, datanetwork):
ifnets = pecan.request.dbapi.interface_datanetwork_get_by_datanetwork(
datanetwork.uuid)
for i in ifnets:
if i.forihostid == interface.forihostid:
msg = _("Data interface %(ifname)s is already "
"attached to this Data Network: "
"%(datanetwork)s." %
{'ifname': i.ifname, 'datanetwork': datanetwork.name})
raise wsme.exc.ClientSideError(msg)
@staticmethod
def _get_interface_id(interface_uuid):
interface = pecan.request.dbapi.iinterface_get(interface_uuid)

View File

@ -2007,12 +2007,20 @@ 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)
if i.ifclass == constants.INTERFACE_CLASS_PLATFORM:
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)
else:
interface_datanetworks = pecan.request.dbapi.interface_datanetwork_get_by_interface(i.id)
for ifdn in interface_datanetworks:
ifdndict = {}
ifdndict['interface_id'] = newIf.id
ifdndict['datanetwork_id'] = ifdn.datanetwork_id
pecan.request.dbapi.interface_datanetwork_create(ifdndict)
# Generate the uses/used_by relationships
for i in newIfList:
@ -2606,14 +2614,22 @@ 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)
if interface.ifclass == constants.INTERFACE_CLASS_PLATFORM:
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)
else:
interface_datanetworks = pecan.request.dbapi.interface_datanetwork_get_by_interface(interface.id)
for ifdn in interface_datanetworks:
ifdndict = {}
ifdndict['interface_id'] = hinterface.id
ifdndict['datanetwork_id'] = ifdn.datanetwork_id
pecan.request.dbapi.interface_datanetwork_create(ifdndict)
except Exception as e:
# Delete all Host's interfaces
@ -2678,14 +2694,22 @@ 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)
if i.ifclass == constants.INTERFACE_CLASS_PLATFORM:
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)
else:
interface_datanetworks = pecan.request.dbapi.interface_datanetwork_get_by_interface(i.id)
for ifdn in interface_datanetworks:
ifdndict = {}
ifdndict['interface_id'] = hinterface.id
ifdndict['datanetwork_id'] = ifdn.datanetwork_id
pecan.request.dbapi.interface_datanetwork_create(ifdndict)
for r in profile.routes.get(i.uuid, []):
pecan.request.dbapi.route_create(hinterface.id, r)

View File

@ -307,17 +307,23 @@ class InterfaceTestCase(base.FunctionalTest):
interface = dbutils.post_get_test_interface(
ifname=ifname,
ifclass=ifclass,
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']
iface = self.dbapi.iinterface_get(interface['uuid'])
if ifclass == constants.INTERFACE_CLASS_PLATFORM and networktype:
network = self.dbapi.network_get_by_type(networktype)
iface = self.dbapi.iinterface_get(interface['uuid'])
dbutils.create_test_interface_network(
interface_id=iface.id,
network_id=network.id)
elif ifclass == constants.INTERFACE_CLASS_DATA and datanetworks:
for dn_name in datanetworks:
dn = self.dbapi.datanetworks_get_all({'name': dn_name})
if dn:
dbutils.create_test_interface_datanetwork(
interface_id=iface.id,
datanetwork_id=dn.id)
self.profile['interfaces'].append(interface)
self.profile['ports'].append(port)
@ -342,7 +348,6 @@ class InterfaceTestCase(base.FunctionalTest):
ifclass=ifclass,
uses=[iface1['ifname'], iface2['ifname']],
txhashpolicy='layer2',
datanetworks=datanetworks,
forihostid=host.id, ihost_uuid=host.uuid)
lacp_types = [constants.NETWORK_TYPE_MGMT,
@ -354,8 +359,20 @@ class InterfaceTestCase(base.FunctionalTest):
response = self._post_and_check(interface, expect_errors)
if expect_errors is False:
interface_uuid = response.json['uuid']
interface['uuid'] = interface_uuid
interface['uuid'] = response.json['uuid']
iface = self.dbapi.iinterface_get(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=iface.id,
network_id=network.id)
elif ifclass == constants.INTERFACE_CLASS_DATA and datanetworks:
for dn_name in datanetworks:
dn = self.dbapi.datanetworks_get_all({'name': dn_name})
if dn:
dbutils.create_test_interface_datanetwork(
interface_id=iface.id,
datanetwork_id=dn.id)
iface1['used_by'].append(interface['ifname'])
iface2['used_by'].append(interface['ifname'])
@ -384,17 +401,24 @@ class InterfaceTestCase(base.FunctionalTest):
ifclass=ifclass,
vlan_id=vlan_id,
uses=[lower_iface['ifname']],
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']
iface = self.dbapi.iinterface_get(interface['uuid'])
if ifclass == constants.INTERFACE_CLASS_PLATFORM and networktype:
interface['uuid'] = response.json['uuid']
network = self.dbapi.network_get_by_type(networktype)
iface = self.dbapi.iinterface_get(interface['uuid'])
dbutils.create_test_interface_network(
interface_id=iface.id,
network_id=network.id)
elif ifclass == constants.INTERFACE_CLASS_DATA and datanetworks:
for dn_name in datanetworks:
dn = self.dbapi.datanetworks_get_all({'name': dn_name})
if dn:
dbutils.create_test_interface_datanetwork(
interface_id=iface.id,
datanetwork_id=dn.id)
self.profile['interfaces'].append(interface)
return interface
@ -1560,12 +1584,21 @@ class TestPost(InterfaceTestCase):
expect_errors=True)
# Expected message:
# Data network(s) not supported for non-data interfaces.
# An interface with interface class platform cannot assign datanetworks.
def test_create_nondata_data_network(self):
self._create_worker_bond(
bond_iface = self._create_worker_bond(
'pxeboot', constants.NETWORK_TYPE_PXEBOOT,
constants.INTERFACE_CLASS_PLATFORM,
datanetworks='group0-data0', expect_errors=True)
constants.INTERFACE_CLASS_PLATFORM)
iface = self.dbapi.iinterface_get(bond_iface['uuid'])
datanetworks = self.dbapi.datanetworks_get_all({'name': 'group0-data0'})
for dn in datanetworks:
iface_dn = dbutils.post_get_test_interface_datanetwork(
interface_uuid=iface.uuid,
datanetwork_uuid=dn.uuid)
response = self.post_json('/interface_datanetworks', iface_dn, 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'])
# Expected message: Name must be unique
def test_create_invalid_ae_name(self):
@ -1585,14 +1618,23 @@ class TestPost(InterfaceTestCase):
expect_errors=True)
# Expected message:
# Data network(s) not supported for non-data interfaces
# An interface with interface class platform cannot assign datanetworks.
def test_create_invalid_mgmt_data_ethernet(self):
self._create_ethernet('shared',
port, mgmt_if = self._create_ethernet('shared',
networktype=constants.NETWORK_TYPE_MGMT,
ifclass=constants.INTERFACE_CLASS_PLATFORM,
datanetworks='group0-data0',
host=self.worker,
expect_errors=True)
host=self.worker)
iface = self.dbapi.iinterface_get(mgmt_if['uuid'])
datanetworks = self.dbapi.datanetworks_get_all({'name': 'group0-data0'})
for dn in datanetworks:
iface_dn = dbutils.post_get_test_interface_datanetwork(
interface_uuid=iface.uuid,
datanetwork_uuid=dn.uuid)
response = self.post_json('/interface_datanetworks', iface_dn,
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 TestCpePost(InterfaceTestCase):
@ -1653,10 +1695,19 @@ class TestCpePost(InterfaceTestCase):
# assigned to a VLAN interface
def test_create_invalid_vlan_with_vlan_data_network(self):
port, lower = self._create_ethernet('eth1', constants.NETWORK_TYPE_NONE)
self._create_vlan('vlan2', networktype=constants.NETWORK_TYPE_DATA,
vlan_if = self._create_vlan('vlan2', networktype=constants.NETWORK_TYPE_DATA,
ifclass=constants.INTERFACE_CLASS_DATA,
datanetworks='group0-data0',
vlan_id=2, lower_iface=lower, expect_errors=True)
vlan_id=2, lower_iface=lower)
iface = self.dbapi.iinterface_get(vlan_if['uuid'])
datanetworks = self.dbapi.datanetworks_get_all({'name': 'group0-data0'})
for dn in datanetworks:
iface_dn = dbutils.post_get_test_interface_datanetwork(
interface_uuid=iface.uuid,
datanetwork_uuid=dn.uuid)
response = self.post_json('/interface_datanetworks', iface_dn, 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'])
@testtools.skip("deprecate neutron bind interface")
@mock.patch.object(dbsql_api.Connection, 'iinterface_destroy')
@ -1687,32 +1738,31 @@ class TestCpePost(InterfaceTestCase):
# Expected error: Data interface data0 is already attached to this
# Data Network: group0-data0.
def test_create_invalid_data_network_used(self):
self._create_ethernet('data0',
port1, data0_if = self._create_ethernet('data0',
networktype=constants.NETWORK_TYPE_DATA,
ifclass=constants.INTERFACE_CLASS_DATA,
datanetworks='group0-data0')
self._create_ethernet('data1',
ifclass=constants.INTERFACE_CLASS_DATA)
iface = self.dbapi.iinterface_get(data0_if['uuid'])
datanetworks = self.dbapi.datanetworks_get_all({'name': 'group0-data0'})
for dn in datanetworks:
iface_dn = dbutils.post_get_test_interface_datanetwork(
interface_uuid=iface.uuid,
datanetwork_uuid=dn.uuid)
response = self.post_json('/interface_datanetworks', iface_dn,
expect_errors=False)
port2, data1_if = self._create_ethernet('data1',
networktype=constants.NETWORK_TYPE_DATA,
ifclass=constants.INTERFACE_CLASS_DATA,
datanetworks='group0-data0',
expect_errors=True)
# Expected error: Data network \'group0-dataXX\' does not exist.
def test_create_invalid_data_network_not_exist(self):
self._create_ethernet('data0',
networktype=constants.NETWORK_TYPE_DATA,
ifclass=constants.INTERFACE_CLASS_DATA,
datanetworks='group0-dataXX',
expect_errors=True)
# Expected error: Specifying duplicate provider network 'group0-data1'
# is not permitted
def test_create_invalid_duplicate_data_network(self):
self._create_ethernet('data0',
networktype=constants.NETWORK_TYPE_DATA,
ifclass=constants.INTERFACE_CLASS_DATA,
datanetworks='group0-data1,group0-data1',
expect_errors=True)
ifclass=constants.INTERFACE_CLASS_DATA)
iface = self.dbapi.iinterface_get(data1_if['uuid'])
datanetworks = self.dbapi.datanetworks_get_all({'name': 'group0-data0'})
for dn in datanetworks:
iface_dn = dbutils.post_get_test_interface_datanetwork(
interface_uuid=iface.uuid,
datanetwork_uuid=dn.uuid)
response = self.post_json('/interface_datanetworks', iface_dn,
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 TestCpePatch(InterfaceTestCase):

View File

@ -659,13 +659,6 @@ def create_test_ethernet_port(**kw):
def post_get_test_interface(**kw):
datanetworks = kw.get('datanetworks') or ""
if datanetworks:
datanetworks_list = datanetworks.split(',')
else:
datanetworks_list = []
interface = {
'forihostid': kw.get('forihostid'),
'ihost_uuid': kw.get('ihost_uuid'),
@ -676,7 +669,6 @@ def post_get_test_interface(**kw):
'ifclass': kw.get("ifclass"),
'aemode': kw.get('aemode', 'balanced'),
'txhashpolicy': kw.get('txhashpolicy', 'layer2'),
'datanetworks': datanetworks_list,
'vlan_id': kw.get('vlan_id'),
'uses': kw.get('uses', None),
'used_by': kw.get('used_by', []),
@ -691,13 +683,6 @@ def post_get_test_interface(**kw):
def get_test_interface(**kw):
datanetworks = kw.get('datanetworks') or ""
if datanetworks:
datanetworks_list = datanetworks.split(',')
else:
datanetworks_list = []
interface = {
'id': kw.get('id'),
'uuid': kw.get('uuid'),
@ -711,7 +696,6 @@ def get_test_interface(**kw):
'networktypelist': kw.get('networktypelist', []),
'aemode': kw.get('aemode'),
'txhashpolicy': kw.get('txhashpolicy', None),
'datanetworks': datanetworks_list,
'vlan_id': kw.get('vlan_id', None),
'uses': kw.get('uses', []),
'used_by': kw.get('used_by', []),
@ -802,6 +786,37 @@ def post_get_test_interface_network(**kw):
return inv
def get_test_interface_datanetwork(**kw):
inv = {
'id': kw.get('id'),
'uuid': kw.get('uuid'),
'interface_uuid': kw.get('interface_uuid'),
'datanetwork_uuid': kw.get('datanetwork_uuid'),
}
return inv
def create_test_interface_datanetwork(**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.
"""
interface_datanetwork = get_test_interface_datanetwork(**kw)
if 'id' not in kw:
del interface_datanetwork['id']
dbapi = db_api.get_instance()
return dbapi.interface_datanetwork_create(interface_datanetwork)
def post_get_test_interface_datanetwork(**kw):
inv = {
'interface_uuid': kw.get('interface_uuid'),
'datanetwork_uuid': kw.get('datanetwork_uuid'),
}
return inv
def get_test_storage_tier(**kw):
tier = {
'id': kw.get('id', 321),