1926 lines
86 KiB
Python
1926 lines
86 KiB
Python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
# -*- encoding: utf-8 -*-
|
|
#
|
|
#
|
|
# Copyright (c) 2013-2016 Wind River Systems, Inc.
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
#
|
|
|
|
"""
|
|
Tests for the API /interfaces/ methods.
|
|
"""
|
|
|
|
import mock
|
|
import testtools
|
|
from six.moves import http_client
|
|
|
|
from sysinv.api.controllers.v1 import interface as api_if_v1
|
|
from sysinv.api.controllers.v1 import utils as api_utils
|
|
from sysinv.common import constants
|
|
from sysinv.conductor import rpcapi
|
|
from sysinv.tests.api import base
|
|
from sysinv.tests.db import utils as dbutils
|
|
from sysinv.db import api as db_api
|
|
from sysinv.db.sqlalchemy import api as dbsql_api
|
|
from sysinv.openstack.common.rpc import common as rpc_common
|
|
|
|
|
|
providernet_list = {
|
|
'group0-data1': {
|
|
"status": "ACTIVE", "description": None,
|
|
"mtu": 1500,
|
|
"ranges": [
|
|
{"minimum": 700,
|
|
"name": "group0-data1-r3-0",
|
|
"tenant_id": "7e0ec7688fb64cf89c9c4fc2e2bd4c94",
|
|
"shared": False,
|
|
"id": "54a6eb56-fa1d-42fe-b32e-de2055bab591",
|
|
"maximum": 715,
|
|
"description": None
|
|
}],
|
|
"vlan_transparent": False,
|
|
"type": "vlan",
|
|
"id": "237848e3-4f7b-4f74-bf35-d4da470be228",
|
|
"name": "group0-data1"},
|
|
'group0-data0': {
|
|
"status": "ACTIVE", "description": None,
|
|
"mtu": 1500,
|
|
"ranges": [
|
|
{"minimum": 600, "name": "group0-data0-r1-0",
|
|
"tenant_id": "3103030ac5a64dc6a6f0c05da79c5c3c",
|
|
"shared": False,
|
|
"id": "62b0d1aa-a4c7-47a3-9363-6726720c89a9",
|
|
"maximum": 615, "description": None}],
|
|
"vlan_transparent": False,
|
|
"type": "vlan",
|
|
"id": "3dee9198-fc3c-4313-a5c5-7b72a4bad57e",
|
|
"name": "group0-data0"},
|
|
'group0-data0b': {
|
|
"status": "ACTIVE", "description": None,
|
|
"mtu": 1500,
|
|
"ranges": [
|
|
{"minimum": 616, "name": "group0-data0b-r2-0",
|
|
"tenant_id": None, "shared": True,
|
|
"id": "7a133887-fe6d-4976-a006-d12948c9498d",
|
|
"maximum": 631, "description": None}],
|
|
"vlan_transparent": False,
|
|
"type": "vlan",
|
|
"id": "83aa5122-49fb-4b97-8cd8-a201dd2d5b0e",
|
|
"name": "group0-data0b"},
|
|
'group0-ext0': {
|
|
"status": "ACTIVE", "description": None,
|
|
"mtu": 1500,
|
|
"ranges": [{"description": None, "minimum": 4,
|
|
"id": "72f21b11-6d17-486e-a4e6-4eaf5f00f23e",
|
|
"name": "group0-ext0-r0-0",
|
|
"tenant_id": None, "maximum": 4,
|
|
"shared": True,
|
|
"vxlan": {"group": "239.0.2.1",
|
|
"port": 8472, "ttl": 10}}],
|
|
"vlan_transparent": False,
|
|
"type": "vxlan",
|
|
"id": "da9f7bb1-2114-4ffd-8a4c-9ca215d98fa2",
|
|
"name": "group0-ext0"},
|
|
'group0-ext1': {
|
|
"status": "ACTIVE", "description": None,
|
|
"mtu": 1500,
|
|
"ranges": [{"description": None, "minimum": 4,
|
|
"id": "72f21b11-6d17-486e-a4e6-4eaf5f00f23e",
|
|
"name": "group0-ext1-r0-0",
|
|
"tenant_id": None, "maximum": 4,
|
|
"shared": True,
|
|
"vxlan": {"group": "239.0.2.1",
|
|
"port": 8472, "ttl": 10}}],
|
|
"vlan_transparent": False,
|
|
"type": "vxlan",
|
|
"id": "da9f7bb1-2114-4ffd-8a4c-9ca215d98fa3",
|
|
"name": "group0-ext1"},
|
|
'group0-ext2': {
|
|
"status": "ACTIVE", "description": None,
|
|
"mtu": 1500,
|
|
"ranges": [{"description": None, "minimum": 4,
|
|
"id": "72f21b11-6d17-486e-a4e6-4eaf5f00f23e",
|
|
"name": "group0-ext2-r0-0",
|
|
"tenant_id": None, "maximum": 4,
|
|
"shared": True,
|
|
"vxlan": {"group": "239.0.2.1",
|
|
"port": 8472, "ttl": 10}}],
|
|
"vlan_transparent": False,
|
|
"type": "vxlan",
|
|
"id": "da9f7bb1-2114-4ffd-8a4c-9ca215d98fa4",
|
|
"name": "group0-ext2"},
|
|
'group0-ext3': {
|
|
"status": "ACTIVE", "description": None,
|
|
"mtu": 1500,
|
|
"ranges": [{"description": None, "minimum": 4,
|
|
"id": "72f21b11-6d17-486e-a4e6-4eaf5f00f23e",
|
|
"name": "group0-ext2-r0-0",
|
|
"tenant_id": None, "maximum": 4,
|
|
"shared": True,
|
|
"vxlan": {"group": "239.0.2.1",
|
|
"port": 8472, "ttl": 10}}],
|
|
"vlan_transparent": False,
|
|
"type": "vxlan",
|
|
"id": "da9f7bb1-2114-4ffd-8a4c-9ca215d98fa5",
|
|
"name": "group0-ext3"},
|
|
'group0-flat': {
|
|
"status": "ACTIVE", "description": None,
|
|
"mtu": 1500,
|
|
"ranges": [{"description": None, "minimum": 4,
|
|
"id": "72f21b11-6d17-486e-a4e6-4eaf5f00f23e",
|
|
"name": "group0-flat-r0-0",
|
|
"tenant_id": None, "maximum": 4,
|
|
"shared": True,
|
|
"vxlan": {"group": "239.0.2.1",
|
|
"port": 8472, "ttl": 10}}],
|
|
"vlan_transparent": False,
|
|
"type": "flat",
|
|
"id": "da9f7bb1-2114-4ffd-8a4c-9ca215d98fa6",
|
|
"name": "group0-flat"}
|
|
}
|
|
|
|
|
|
class InterfaceTestCase(base.FunctionalTest):
|
|
def _setup_configuration(self):
|
|
pass
|
|
|
|
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',
|
|
'enp0s19': '08:00:27:ea:93:8e'}
|
|
self.addCleanup(p.stop)
|
|
|
|
p = mock.patch.object(rpcapi.ConductorAPI,
|
|
'iinterface_get_providernets')
|
|
self.mock_iinterface_get_providernets = p.start()
|
|
self.mock_iinterface_get_providernets.return_value = providernet_list
|
|
self.addCleanup(p.stop)
|
|
|
|
p = mock.patch.object(api_utils, 'get_sdn_l3_mode_enabled')
|
|
self.mock_sdn_l3_mode_enabled = p.start()
|
|
self.mock_sdn_l3_mode_enabled.return_value = True
|
|
self.addCleanup(p.stop)
|
|
|
|
self._setup_context()
|
|
|
|
def _get_path(self, path=None):
|
|
if path:
|
|
return '/iinterfaces/' + path
|
|
else:
|
|
return '/iinterfaces'
|
|
|
|
def _create_host(self, personality, subfunction=None,
|
|
mgmt_mac=None, mgmt_ip=None,
|
|
sdn_enabled=True, admin=None,
|
|
invprovision=constants.PROVISIONED):
|
|
if personality == constants.CONTROLLER:
|
|
self.system = dbutils.create_test_isystem(sdn_enabled=sdn_enabled)
|
|
self.address_pool1 = dbutils.create_test_address_pool(
|
|
id=1,
|
|
network='192.168.204.0',
|
|
name='management',
|
|
ranges=[['192.168.204.2', '192.168.204.254']],
|
|
prefix=24)
|
|
self.address_pool2 = dbutils.create_test_address_pool(
|
|
id=2,
|
|
network='192.168.205.0',
|
|
name='infrastructure',
|
|
ranges=[['192.168.205.2', '192.168.205.254']],
|
|
prefix=24)
|
|
self.address_pool_oam = dbutils.create_test_address_pool(
|
|
id=3,
|
|
network='128.224.150.0',
|
|
name='oam',
|
|
ranges=[['128.224.150.1', '128.224.151.254']],
|
|
prefix=23)
|
|
self.address_pool_v6 = dbutils.create_test_address_pool(
|
|
id=4,
|
|
network='abde::',
|
|
name='ipv6',
|
|
ranges=[['abde::2', 'abde::ffff:ffff:ffff:fffe']],
|
|
prefix=64)
|
|
self.address_pool_pxeboot = dbutils.create_test_address_pool(
|
|
id=5,
|
|
network='192.168.202.0',
|
|
name='pxeboot',
|
|
ranges=[['192.168.202.2', '192.168.202.254']],
|
|
prefix=23)
|
|
self.mgmt_network = dbutils.create_test_network(
|
|
id=1,
|
|
name='mgmt',
|
|
type=constants.NETWORK_TYPE_MGMT,
|
|
link_capacity=1000,
|
|
vlan_id=2,
|
|
address_pool_id=self.address_pool1.id)
|
|
self.infra_network = dbutils.create_test_network(
|
|
id=2,
|
|
name='infra',
|
|
type=constants.NETWORK_TYPE_INFRA,
|
|
link_capacity=10000,
|
|
vlan_id=3,
|
|
address_pool_id=self.address_pool2.id)
|
|
self.oam_network = dbutils.create_test_network(
|
|
id=3,
|
|
name='oam',
|
|
type=constants.NETWORK_TYPE_OAM,
|
|
address_pool_id=self.address_pool_oam.id)
|
|
self.oam_address = dbutils.create_test_address(
|
|
family=2,
|
|
address='10.10.10.3',
|
|
prefix=24,
|
|
name='controller-0-oam',
|
|
address_pool_id=self.address_pool_oam.id)
|
|
self.pxeboot_network = dbutils.create_test_network(
|
|
id=4,
|
|
type=constants.NETWORK_TYPE_PXEBOOT,
|
|
address_pool_id=self.address_pool_pxeboot.id)
|
|
self.pxeboot_address = dbutils.create_test_address(
|
|
family=2,
|
|
address='192.168.202.3',
|
|
prefix=24,
|
|
name='controller-0-pxeboot',
|
|
address_pool_id=self.address_pool_pxeboot.id)
|
|
|
|
host = dbutils.create_test_ihost(
|
|
hostname='%s-0' % personality,
|
|
forisystemid=self.system.id,
|
|
personality=personality,
|
|
subfunctions=subfunction or personality,
|
|
mgmt_mac=mgmt_mac,
|
|
mgmt_ip=mgmt_ip,
|
|
administrative=admin or constants.ADMIN_UNLOCKED,
|
|
invprovision=invprovision
|
|
)
|
|
if personality == constants.CONTROLLER:
|
|
self.controller = host
|
|
else:
|
|
self.worker = host
|
|
return
|
|
|
|
def _create_datanetworks(self):
|
|
for name, v in providernet_list.items():
|
|
dn_values = {
|
|
'name': name,
|
|
'uuid': v.get('id', None),
|
|
'network_type': v['type'],
|
|
'mtu': v['mtu']}
|
|
if v['type'] == constants.DATANETWORK_TYPE_VXLAN:
|
|
for r in v['ranges']:
|
|
dn_values.update(
|
|
{'multicast_group': r['vxlan'].get('group'),
|
|
'port_num': r['vxlan'].get('port'),
|
|
'ttl': r['vxlan'].get('ttl'),
|
|
'mode': r['vxlan'].get('mode', 'dynamic'),
|
|
})
|
|
|
|
dbutils.create_test_datanetwork(**dn_values)
|
|
|
|
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):
|
|
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,
|
|
name='eth' + str(port_id),
|
|
host_id=host.id,
|
|
interface_id=interface_id,
|
|
pciaddr='0000:00:00.' + str(port_id + 1),
|
|
dev_id=0)
|
|
|
|
interface_uuid = None
|
|
if not networktype:
|
|
interface = dbutils.create_test_interface(ifname=ifname,
|
|
forihostid=host.id,
|
|
ihost_uuid=host.uuid,
|
|
networks=networks)
|
|
interface_uuid = interface.uuid
|
|
else:
|
|
interface = dbutils.post_get_test_interface(
|
|
ifname=ifname,
|
|
ifclass=ifclass,
|
|
networktype=networktype,
|
|
networks=networks,
|
|
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
|
|
|
|
self.profile['interfaces'].append(interface)
|
|
self.profile['ports'].append(port)
|
|
|
|
return port, interface
|
|
|
|
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)
|
|
port2, iface2 = self._create_ethernet(host=host)
|
|
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):
|
|
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,
|
|
forihostid=host.id, ihost_uuid=host.uuid)
|
|
|
|
lacp_types = [constants.NETWORK_TYPE_MGMT,
|
|
constants.NETWORK_TYPE_PXEBOOT]
|
|
if networktype in lacp_types:
|
|
interface['aemode'] = '802.3ad'
|
|
else:
|
|
interface['aemode'] = 'balanced'
|
|
|
|
response = self._post_and_check(interface, expect_errors)
|
|
if expect_errors is False:
|
|
interface_uuid = response.json['uuid']
|
|
interface['uuid'] = interface_uuid
|
|
|
|
iface1['used_by'].append(interface['ifname'])
|
|
iface2['used_by'].append(interface['ifname'])
|
|
self.profile['interfaces'].append(interface)
|
|
return interface
|
|
|
|
def _create_worker_bond(self, ifname, networktype=None, ifclass=None,
|
|
datanetworks=None, expect_errors=False):
|
|
return self._create_bond(ifname, networktype, ifclass, datanetworks,
|
|
self.worker, expect_errors)
|
|
|
|
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):
|
|
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)
|
|
self.profile['interfaces'].append(interface)
|
|
return interface
|
|
|
|
def _create_worker_vlan(self, ifname, networktype, ifclass, vlan_id,
|
|
lower_iface=None, datanetworks=None,
|
|
host=None, expect_errors=False):
|
|
return self._create_vlan(ifname, networktype, ifclass, vlan_id,
|
|
lower_iface,
|
|
datanetworks, self.worker, expect_errors)
|
|
|
|
def _post_and_check_success(self, ndict):
|
|
response = self.post_json('%s' % self._get_path(), ndict)
|
|
self.assertEqual(http_client.OK, response.status_int)
|
|
return response
|
|
|
|
def _post_and_check_failure(self, ndict):
|
|
response = self.post_json('%s' % self._get_path(), ndict,
|
|
expect_errors=True)
|
|
self.assertEqual(http_client.BAD_REQUEST, response.status_int)
|
|
self.assertEqual('application/json', response.content_type)
|
|
self.assertTrue(response.json['error_message'])
|
|
|
|
def _post_and_check(self, ndict, expect_errors=False):
|
|
response = self.post_json('%s' % self._get_path(), ndict,
|
|
expect_errors)
|
|
if expect_errors:
|
|
self.assertEqual(http_client.BAD_REQUEST, response.status_int)
|
|
self.assertEqual('application/json', response.content_type)
|
|
self.assertTrue(response.json['error_message'])
|
|
else:
|
|
self.assertEqual(http_client.OK, response.status_int)
|
|
return response
|
|
|
|
def _create_and_apply_profile(self, host):
|
|
ifprofile = {
|
|
'ihost_uuid': host.uuid,
|
|
'profilename': 'ifprofile-node1',
|
|
'profiletype': constants.PROFILE_TYPE_INTERFACE
|
|
}
|
|
response = self.post_json('/iprofile', ifprofile)
|
|
self.assertEqual(http_client.OK, response.status_int)
|
|
|
|
list_data = self.get_json('/iprofile')
|
|
profile_uuid = list_data['iprofiles'][0]['uuid']
|
|
|
|
self.get_json('/iprofile/%s/iinterfaces' % profile_uuid)
|
|
self.get_json('/iprofile/%s/ethernet_ports' % profile_uuid)
|
|
|
|
result = self.patch_dict_json('/ihosts/%s' % host.id,
|
|
headers={'User-Agent': 'sysinv'},
|
|
action=constants.APPLY_PROFILE_ACTION,
|
|
iprofile_uuid=profile_uuid)
|
|
self.assertEqual(http_client.OK, result.status_int)
|
|
|
|
def is_interface_equal(self, first, second):
|
|
for key in first:
|
|
if key in second:
|
|
self.assertEqual(first[key], second[key])
|
|
|
|
def _setup_context(self):
|
|
self.profile = {'host':
|
|
{'personality': constants.CONTROLLER,
|
|
'hostname': constants.CONTROLLER_0_HOSTNAME},
|
|
'interfaces': [],
|
|
'ports': [],
|
|
'addresses': [],
|
|
'routes': [],
|
|
'interface_networks': []}
|
|
self.system = None
|
|
self.controller = None
|
|
self.worker = None
|
|
self._setup_configuration()
|
|
|
|
def test_interface(self):
|
|
if len(self.profile['interfaces']) == 0:
|
|
self.assertFalse(False)
|
|
|
|
|
|
class InterfaceControllerEthernet(InterfaceTestCase):
|
|
|
|
def _setup_configuration(self):
|
|
# Setup a sample configuration where all platform interfaces are
|
|
# ethernet interfaces.
|
|
self._create_host(constants.CONTROLLER, admin=constants.ADMIN_LOCKED)
|
|
self._create_ethernet('oam', constants.NETWORK_TYPE_OAM)
|
|
self._create_ethernet('mgmt', constants.NETWORK_TYPE_MGMT)
|
|
self._create_ethernet('infra', constants.NETWORK_TYPE_INFRA)
|
|
self.get_json('/ihosts/%s/iinterfaces' % self.controller.uuid)
|
|
|
|
def setUp(self):
|
|
super(InterfaceControllerEthernet, self).setUp()
|
|
|
|
def test_controller_ethernet_profile(self):
|
|
self._create_and_apply_profile(self.controller)
|
|
|
|
|
|
class InterfaceControllerBond(InterfaceTestCase):
|
|
|
|
def _setup_configuration(self):
|
|
# Setup a sample configuration where all platform interfaces are
|
|
# aggregated ethernet interfaces.
|
|
self._create_host(constants.CONTROLLER, admin=constants.ADMIN_LOCKED)
|
|
self._create_bond('oam', constants.NETWORK_TYPE_OAM)
|
|
self._create_bond('mgmt', constants.NETWORK_TYPE_MGMT)
|
|
self._create_bond('infra', constants.NETWORK_TYPE_INFRA)
|
|
|
|
def setUp(self):
|
|
super(InterfaceControllerBond, self).setUp()
|
|
|
|
def test_controller_bond_profile(self):
|
|
self._create_and_apply_profile(self.controller)
|
|
|
|
|
|
class InterfaceControllerVlanOverBond(InterfaceTestCase):
|
|
|
|
def _setup_configuration(self):
|
|
# Setup a sample configuration where all platform interfaces are
|
|
# vlan interfaces over aggregated ethernet interfaces
|
|
self._create_host(constants.CONTROLLER, admin=constants.ADMIN_LOCKED)
|
|
bond = self._create_bond('pxeboot', constants.NETWORK_TYPE_PXEBOOT)
|
|
self._create_vlan('oam', constants.NETWORK_TYPE_OAM,
|
|
constants.INTERFACE_CLASS_PLATFORM, 1, bond)
|
|
self._create_vlan('mgmt', constants.NETWORK_TYPE_MGMT,
|
|
constants.INTERFACE_CLASS_PLATFORM, 2, bond)
|
|
self._create_vlan('infra', constants.NETWORK_TYPE_INFRA,
|
|
constants.INTERFACE_CLASS_PLATFORM, 3, bond)
|
|
# self._create_ethernet('none')
|
|
|
|
def setUp(self):
|
|
super(InterfaceControllerVlanOverBond, self).setUp()
|
|
|
|
def test_controller_vlan_over_bond_profile(self):
|
|
self._create_and_apply_profile(self.controller)
|
|
|
|
|
|
class InterfaceControllerVlanOverEthernet(InterfaceTestCase):
|
|
|
|
def _setup_configuration(self):
|
|
# Setup a sample configuration where all platform interfaces are
|
|
# vlan interfaces over ethernet interfaces
|
|
self._create_host(constants.CONTROLLER, admin=constants.ADMIN_LOCKED)
|
|
port, iface = self._create_ethernet(
|
|
'pxeboot', constants.NETWORK_TYPE_PXEBOOT)
|
|
self._create_vlan('oam', constants.NETWORK_TYPE_OAM,
|
|
constants.INTERFACE_CLASS_PLATFORM, 1, iface)
|
|
self._create_vlan('mgmt', constants.NETWORK_TYPE_MGMT,
|
|
constants.INTERFACE_CLASS_PLATFORM, 2, iface)
|
|
self._create_vlan('infra', constants.NETWORK_TYPE_INFRA,
|
|
constants.INTERFACE_CLASS_PLATFORM, 3, iface)
|
|
# self._create_ethernet_profile('none')
|
|
|
|
def setUp(self):
|
|
super(InterfaceControllerVlanOverEthernet, self).setUp()
|
|
|
|
def test_controller_vlan_over_ethernet_profile(self):
|
|
self._create_and_apply_profile(self.controller)
|
|
|
|
|
|
class InterfaceComputeEthernet(InterfaceTestCase):
|
|
|
|
def _setup_configuration(self):
|
|
# Setup a sample configuration where the personality is set to a
|
|
# worker and all interfaces are ethernet interfaces.
|
|
self._create_host(constants.CONTROLLER, admin=constants.ADMIN_UNLOCKED)
|
|
self._create_datanetworks()
|
|
self._create_ethernet('oam', constants.NETWORK_TYPE_OAM)
|
|
self._create_ethernet('mgmt', constants.NETWORK_TYPE_MGMT)
|
|
self._create_ethernet('infra', constants.NETWORK_TYPE_INFRA)
|
|
|
|
self._create_host(constants.WORKER, constants.WORKER,
|
|
mgmt_mac='01:02.03.04.05.C0',
|
|
mgmt_ip='192.168.24.12',
|
|
admin=constants.ADMIN_LOCKED)
|
|
self._create_ethernet('mgmt', constants.NETWORK_TYPE_MGMT,
|
|
host=self.worker)
|
|
self._create_ethernet('infra', constants.NETWORK_TYPE_INFRA,
|
|
host=self.worker)
|
|
self._create_ethernet('data',
|
|
constants.NETWORK_TYPE_DATA,
|
|
constants.INTERFACE_CLASS_DATA,
|
|
'group0-data0', host=self.worker)
|
|
self._create_ethernet('sriov',
|
|
constants.NETWORK_TYPE_PCI_SRIOV,
|
|
constants.INTERFACE_CLASS_PCI_SRIOV,
|
|
'group0-data1', host=self.worker)
|
|
self._create_ethernet('pthru',
|
|
constants.NETWORK_TYPE_PCI_PASSTHROUGH,
|
|
constants.INTERFACE_CLASS_PCI_PASSTHROUGH,
|
|
'group0-ext0', host=self.worker)
|
|
port, iface = (
|
|
self._create_ethernet('slow',
|
|
constants.NETWORK_TYPE_DATA,
|
|
constants.INTERFACE_CLASS_DATA,
|
|
'group0-ext1', host=self.worker))
|
|
port['dpdksupport'] = False
|
|
port, iface = (
|
|
self._create_ethernet('mlx4',
|
|
constants.NETWORK_TYPE_DATA,
|
|
constants.INTERFACE_CLASS_DATA,
|
|
'group0-ext2', host=self.worker))
|
|
port['driver'] = 'mlx4_core'
|
|
port, iface = (
|
|
self._create_ethernet('mlx5',
|
|
constants.NETWORK_TYPE_DATA,
|
|
constants.INTERFACE_CLASS_DATA,
|
|
'group0-ext3', host=self.worker))
|
|
port['driver'] = 'mlx5_core'
|
|
|
|
def setUp(self):
|
|
super(InterfaceComputeEthernet, self).setUp()
|
|
|
|
def test_worker_ethernet_profile(self):
|
|
self._create_and_apply_profile(self.worker)
|
|
|
|
|
|
class InterfaceComputeVlanOverEthernet(InterfaceTestCase):
|
|
|
|
def _setup_configuration(self):
|
|
# Setup a sample configuration where the personality is set to a
|
|
# controller and all interfaces are vlan interfaces over ethernet
|
|
# interfaces.
|
|
self._create_host(constants.CONTROLLER)
|
|
self._create_datanetworks()
|
|
port, iface = self._create_ethernet(
|
|
'pxeboot', constants.NETWORK_TYPE_PXEBOOT)
|
|
self._create_vlan('oam', constants.NETWORK_TYPE_OAM,
|
|
constants.INTERFACE_CLASS_PLATFORM, 1, iface)
|
|
self._create_vlan('mgmt', constants.NETWORK_TYPE_MGMT,
|
|
constants.INTERFACE_CLASS_PLATFORM, 2, iface)
|
|
self._create_vlan('infra', constants.NETWORK_TYPE_INFRA,
|
|
constants.INTERFACE_CLASS_PLATFORM, 3, iface)
|
|
|
|
# Setup a sample configuration where the personality is set to a
|
|
# worker and all interfaces are vlan interfaces over ethernet
|
|
# interfaces.
|
|
self._create_host(constants.WORKER, admin=constants.ADMIN_LOCKED)
|
|
port, iface = self._create_ethernet(
|
|
'pxeboot', constants.NETWORK_TYPE_PXEBOOT, host=self.worker)
|
|
self._create_worker_vlan('mgmt', constants.NETWORK_TYPE_MGMT,
|
|
constants.INTERFACE_CLASS_PLATFORM, 2, iface)
|
|
self._create_worker_vlan('infra', constants.NETWORK_TYPE_INFRA,
|
|
constants.INTERFACE_CLASS_PLATFORM, 3)
|
|
self._create_worker_vlan('data', constants.INTERFACE_CLASS_DATA,
|
|
constants.NETWORK_TYPE_DATA, 5,
|
|
datanetworks='group0-ext0')
|
|
self._create_ethernet('sriov',
|
|
constants.NETWORK_TYPE_PCI_SRIOV,
|
|
constants.INTERFACE_CLASS_PCI_SRIOV,
|
|
'group0-data0', host=self.worker)
|
|
self._create_ethernet('pthru',
|
|
constants.NETWORK_TYPE_PCI_PASSTHROUGH,
|
|
constants.INTERFACE_CLASS_PCI_PASSTHROUGH,
|
|
'group0-data1', host=self.worker)
|
|
|
|
def setUp(self):
|
|
super(InterfaceComputeVlanOverEthernet, self).setUp()
|
|
|
|
def test_worker_vlan_over_ethernet_profile(self):
|
|
self._create_and_apply_profile(self.worker)
|
|
|
|
|
|
class InterfaceComputeBond(InterfaceTestCase):
|
|
|
|
def _setup_configuration(self):
|
|
# Setup a sample configuration where all platform interfaces are
|
|
# aggregated ethernet interfaces.
|
|
self._create_host(constants.CONTROLLER, admin=constants.ADMIN_UNLOCKED)
|
|
self._create_datanetworks()
|
|
self._create_bond('oam', constants.NETWORK_TYPE_OAM)
|
|
self._create_bond('mgmt', constants.NETWORK_TYPE_MGMT)
|
|
self._create_bond('infra', constants.NETWORK_TYPE_INFRA)
|
|
|
|
# Setup a sample configuration where the personality is set to a
|
|
# worker and all interfaces are aggregated ethernet interfaces.
|
|
self._create_host(constants.WORKER, admin=constants.ADMIN_LOCKED)
|
|
self._create_worker_bond('mgmt', constants.NETWORK_TYPE_MGMT)
|
|
self._create_worker_bond('infra', constants.NETWORK_TYPE_INFRA)
|
|
self._create_worker_bond('data',
|
|
constants.NETWORK_TYPE_DATA,
|
|
constants.INTERFACE_CLASS_DATA,
|
|
datanetworks='group0-data0')
|
|
self._create_ethernet('sriov',
|
|
constants.NETWORK_TYPE_PCI_SRIOV,
|
|
constants.INTERFACE_CLASS_PCI_SRIOV,
|
|
'group0-ext0', host=self.worker)
|
|
self._create_ethernet('pthru',
|
|
constants.NETWORK_TYPE_PCI_PASSTHROUGH,
|
|
constants.INTERFACE_CLASS_PCI_PASSTHROUGH,
|
|
'group0-ext1', host=self.worker)
|
|
|
|
def setUp(self):
|
|
super(InterfaceComputeBond, self).setUp()
|
|
|
|
def test_worker_bond_profile(self):
|
|
self._create_and_apply_profile(self.worker)
|
|
|
|
|
|
class InterfaceComputeVlanOverBond(InterfaceTestCase):
|
|
|
|
def _setup_configuration(self):
|
|
self._create_host(constants.CONTROLLER)
|
|
self._create_datanetworks()
|
|
bond = self._create_bond('pxeboot', constants.NETWORK_TYPE_PXEBOOT,
|
|
constants.INTERFACE_CLASS_PLATFORM)
|
|
self._create_vlan('oam', constants.NETWORK_TYPE_OAM,
|
|
constants.INTERFACE_CLASS_PLATFORM, 1, bond)
|
|
self._create_vlan('mgmt', constants.NETWORK_TYPE_MGMT,
|
|
constants.INTERFACE_CLASS_PLATFORM, 2, bond)
|
|
self._create_vlan('infra', constants.NETWORK_TYPE_INFRA,
|
|
constants.INTERFACE_CLASS_PLATFORM, 3, bond)
|
|
|
|
# Setup a sample configuration where the personality is set to a
|
|
# worker and all interfaces are vlan interfaces over aggregated
|
|
# ethernet interfaces.
|
|
self._create_host(constants.WORKER, admin=constants.ADMIN_LOCKED)
|
|
bond = self._create_worker_bond('pxeboot',
|
|
constants.NETWORK_TYPE_PXEBOOT,
|
|
constants.INTERFACE_CLASS_PLATFORM)
|
|
self._create_worker_vlan('mgmt', constants.NETWORK_TYPE_MGMT,
|
|
constants.INTERFACE_CLASS_PLATFORM, 2, bond)
|
|
self._create_worker_vlan('infra', constants.NETWORK_TYPE_INFRA,
|
|
constants.INTERFACE_CLASS_PLATFORM, 3,
|
|
bond)
|
|
bond2 = self._create_worker_bond('bond2', constants.NETWORK_TYPE_NONE)
|
|
self._create_worker_vlan('data',
|
|
constants.NETWORK_TYPE_DATA,
|
|
constants.INTERFACE_CLASS_DATA,
|
|
5, bond2,
|
|
datanetworks='group0-ext0')
|
|
|
|
self._create_worker_bond('bond3', constants.NETWORK_TYPE_NONE)
|
|
|
|
self._create_ethernet('sriov',
|
|
constants.NETWORK_TYPE_PCI_SRIOV,
|
|
constants.INTERFACE_CLASS_PCI_SRIOV,
|
|
'group0-data0', host=self.worker)
|
|
self._create_ethernet('pthru',
|
|
constants.NETWORK_TYPE_PCI_PASSTHROUGH,
|
|
constants.INTERFACE_CLASS_PCI_PASSTHROUGH,
|
|
'group0-data1', host=self.worker)
|
|
|
|
def setUp(self):
|
|
super(InterfaceComputeVlanOverBond, self).setUp()
|
|
|
|
def test_worker_vlan_over_bond_profile(self):
|
|
self._create_and_apply_profile(self.worker)
|
|
|
|
|
|
class InterfaceComputeVlanOverDataEthernet(InterfaceTestCase):
|
|
|
|
def _setup_configuration(self):
|
|
self._create_host(constants.CONTROLLER)
|
|
self._create_datanetworks()
|
|
bond = self._create_bond('pxeboot', constants.NETWORK_TYPE_PXEBOOT)
|
|
self._create_vlan('oam', constants.NETWORK_TYPE_OAM,
|
|
constants.INTERFACE_CLASS_PLATFORM, 1, bond)
|
|
self._create_ethernet('mgmt', constants.NETWORK_TYPE_MGMT)
|
|
self._create_ethernet('infra', constants.NETWORK_TYPE_INFRA)
|
|
|
|
# Setup a sample configuration where the personality is set to a
|
|
# worker and all interfaces are vlan interfaces over data ethernet
|
|
# interfaces.
|
|
self._create_host(constants.WORKER, admin=constants.ADMIN_LOCKED)
|
|
port, iface = (
|
|
self._create_ethernet('data',
|
|
constants.NETWORK_TYPE_DATA,
|
|
constants.INTERFACE_CLASS_DATA,
|
|
'group0-data0', host=self.worker))
|
|
self._create_ethernet('mgmt', constants.NETWORK_TYPE_MGMT,
|
|
host=self.worker)
|
|
self._create_ethernet('infra', constants.NETWORK_TYPE_INFRA,
|
|
host=self.worker)
|
|
self._create_worker_vlan('data2', constants.NETWORK_TYPE_DATA,
|
|
constants.INTERFACE_CLASS_DATA, 5,
|
|
iface, datanetworks='group0-ext0')
|
|
self._create_ethernet('sriov',
|
|
constants.NETWORK_TYPE_PCI_SRIOV,
|
|
constants.INTERFACE_CLASS_PCI_SRIOV,
|
|
'group0-ext1', host=self.worker)
|
|
self._create_ethernet('pthru',
|
|
constants.NETWORK_TYPE_PCI_PASSTHROUGH,
|
|
constants.INTERFACE_CLASS_PCI_PASSTHROUGH,
|
|
'group0-ext2', host=self.worker)
|
|
|
|
def setUp(self):
|
|
super(InterfaceComputeVlanOverDataEthernet, self).setUp()
|
|
|
|
def test_worker_vlan_over_data_ethernet_profile(self):
|
|
self._create_and_apply_profile(self.worker)
|
|
|
|
|
|
class InterfaceCpeEthernet(InterfaceTestCase):
|
|
|
|
def _setup_configuration(self):
|
|
# Setup a sample configuration where the personality is set to a
|
|
# controller with a worker subfunction and all interfaces are
|
|
# ethernet interfaces.
|
|
self._create_host(constants.CONTROLLER, constants.WORKER,
|
|
admin=constants.ADMIN_LOCKED)
|
|
self._create_datanetworks()
|
|
self._create_ethernet('oam', constants.NETWORK_TYPE_OAM)
|
|
self._create_ethernet('mgmt', constants.NETWORK_TYPE_MGMT)
|
|
self._create_ethernet('infra', constants.NETWORK_TYPE_INFRA)
|
|
self._create_ethernet('data', constants.NETWORK_TYPE_DATA,
|
|
constants.INTERFACE_CLASS_DATA,
|
|
'group0-data0')
|
|
self._create_ethernet('sriov', constants.NETWORK_TYPE_PCI_SRIOV,
|
|
constants.INTERFACE_CLASS_PCI_SRIOV,
|
|
'group0-data1')
|
|
self._create_ethernet('pthru', constants.NETWORK_TYPE_PCI_PASSTHROUGH,
|
|
constants.INTERFACE_CLASS_PCI_PASSTHROUGH,
|
|
'group0-ext0')
|
|
port, iface = (
|
|
self._create_ethernet('slow', constants.NETWORK_TYPE_DATA,
|
|
constants.INTERFACE_CLASS_DATA,
|
|
'group0-ext1'))
|
|
port['dpdksupport'] = False
|
|
port, iface = (
|
|
self._create_ethernet('mlx4', constants.NETWORK_TYPE_DATA,
|
|
constants.INTERFACE_CLASS_DATA,
|
|
'group0-ext2'))
|
|
port['driver'] = 'mlx4_core'
|
|
port, iface = (
|
|
self._create_ethernet('mlx5', constants.NETWORK_TYPE_DATA,
|
|
constants.INTERFACE_CLASS_DATA,
|
|
'group0-ext3'))
|
|
|
|
def setUp(self):
|
|
super(InterfaceCpeEthernet, self).setUp()
|
|
|
|
def test_cpe_ethernet_profile(self):
|
|
self._create_and_apply_profile(self.controller)
|
|
|
|
|
|
class InterfaceCpeVlanOverEthernet(InterfaceTestCase):
|
|
|
|
def _setup_configuration(self):
|
|
# Setup a sample configuration where the personality is set to a
|
|
# controller with a worker subfunction and all interfaces are
|
|
# vlan interfaces over ethernet interfaces.
|
|
self._create_host(constants.CONTROLLER, constants.WORKER,
|
|
admin=constants.ADMIN_LOCKED)
|
|
self._create_datanetworks()
|
|
port, iface = self._create_ethernet(
|
|
'pxeboot', constants.NETWORK_TYPE_PXEBOOT)
|
|
self._create_vlan('oam', constants.NETWORK_TYPE_OAM,
|
|
constants.INTERFACE_CLASS_PLATFORM, 1, iface)
|
|
self._create_vlan('mgmt', constants.NETWORK_TYPE_MGMT,
|
|
constants.INTERFACE_CLASS_PLATFORM, 2, iface)
|
|
self._create_vlan('infra', constants.NETWORK_TYPE_INFRA,
|
|
constants.INTERFACE_CLASS_PLATFORM, 3)
|
|
self._create_ethernet('data', constants.NETWORK_TYPE_DATA,
|
|
constants.INTERFACE_CLASS_DATA,
|
|
datanetworks='group0-ext0')
|
|
self._create_ethernet('sriov', constants.NETWORK_TYPE_PCI_SRIOV,
|
|
constants.INTERFACE_CLASS_PCI_SRIOV,
|
|
'group0-ext1')
|
|
self._create_ethernet('pthru', constants.NETWORK_TYPE_PCI_PASSTHROUGH,
|
|
constants.INTERFACE_CLASS_PCI_PASSTHROUGH,
|
|
'group0-ext2')
|
|
|
|
def setUp(self):
|
|
super(InterfaceCpeVlanOverEthernet, self).setUp()
|
|
|
|
def test_cpe_vlan_over_ethernet_profile(self):
|
|
self._create_and_apply_profile(self.controller)
|
|
|
|
|
|
class InterfaceCpeBond(InterfaceTestCase):
|
|
|
|
def _setup_configuration(self):
|
|
# Setup a sample configuration where the personality is set to a
|
|
# controller with a worker subfunction and all interfaces are
|
|
# aggregated ethernet interfaces.
|
|
self._create_host(constants.CONTROLLER,
|
|
subfunction=constants.WORKER,
|
|
admin=constants.ADMIN_LOCKED)
|
|
self._create_datanetworks()
|
|
self._create_bond('oam', constants.NETWORK_TYPE_OAM)
|
|
self._create_bond('mgmt', constants.NETWORK_TYPE_MGMT)
|
|
self._create_bond('infra', constants.NETWORK_TYPE_INFRA)
|
|
self._create_bond('data', constants.NETWORK_TYPE_DATA,
|
|
constants.INTERFACE_CLASS_DATA,
|
|
datanetworks='group0-data0')
|
|
self._create_ethernet('sriov', constants.NETWORK_TYPE_PCI_SRIOV,
|
|
constants.INTERFACE_CLASS_PCI_SRIOV,
|
|
datanetworks='group0-ext0')
|
|
self._create_ethernet('pthru', constants.NETWORK_TYPE_PCI_PASSTHROUGH,
|
|
constants.INTERFACE_CLASS_PCI_PASSTHROUGH,
|
|
datanetworks='group0-ext1')
|
|
|
|
def setUp(self):
|
|
super(InterfaceCpeBond, self).setUp()
|
|
|
|
def test_cpe_bond_profile(self):
|
|
self._create_and_apply_profile(self.controller)
|
|
|
|
|
|
class InterfaceCpeVlanOverBond(InterfaceTestCase):
|
|
|
|
def _setup_configuration(self):
|
|
# Setup a sample configuration where the personality is set to a
|
|
# controller with a worker subfunction and all interfaces are
|
|
# vlan interfaces over aggregated ethernet interfaces.
|
|
self._create_host(constants.CONTROLLER, constants.WORKER,
|
|
admin=constants.ADMIN_LOCKED)
|
|
self._create_datanetworks()
|
|
bond = self._create_bond('pxeboot', constants.NETWORK_TYPE_PXEBOOT)
|
|
self._create_vlan('oam', constants.NETWORK_TYPE_OAM,
|
|
constants.INTERFACE_CLASS_PLATFORM, 1, bond)
|
|
self._create_vlan('mgmt', constants.NETWORK_TYPE_MGMT,
|
|
constants.INTERFACE_CLASS_PLATFORM, 2, bond)
|
|
self._create_vlan('infra', constants.NETWORK_TYPE_INFRA,
|
|
constants.INTERFACE_CLASS_PLATFORM, 3, bond)
|
|
bond2 = self._create_bond('bond4', constants.NETWORK_TYPE_NONE)
|
|
self._create_vlan('data', constants.NETWORK_TYPE_DATA,
|
|
constants.INTERFACE_CLASS_DATA,
|
|
5, bond2,
|
|
datanetworks='group0-ext0')
|
|
self._create_ethernet('sriov', constants.NETWORK_TYPE_PCI_SRIOV,
|
|
constants.INTERFACE_CLASS_PCI_SRIOV,
|
|
'group0-ext1')
|
|
self._create_ethernet('pthru', constants.NETWORK_TYPE_PCI_PASSTHROUGH,
|
|
constants.INTERFACE_CLASS_PCI_PASSTHROUGH,
|
|
'group0-ext2')
|
|
|
|
def setUp(self):
|
|
super(InterfaceCpeVlanOverBond, self).setUp()
|
|
|
|
def test_cpe_vlan_over_bond_profile(self):
|
|
self._create_and_apply_profile(self.controller)
|
|
|
|
|
|
# Test that the unsupported config is rejected
|
|
class InterfaceCpeVlanOverDataEthernet(InterfaceTestCase):
|
|
|
|
def _setup_configuration(self):
|
|
# Setup a sample configuration where the personality is set to a
|
|
# controller with a worker subfunction and all interfaces are
|
|
# vlan interfaces over data ethernet interfaces.
|
|
self._create_host(constants.CONTROLLER, constants.WORKER,
|
|
admin=constants.ADMIN_LOCKED)
|
|
self._create_datanetworks()
|
|
port, iface = (
|
|
self._create_ethernet('data',
|
|
constants.NETWORK_TYPE_DATA,
|
|
constants.INTERFACE_CLASS_DATA,
|
|
'group0-data0'))
|
|
self._create_vlan('oam', constants.NETWORK_TYPE_OAM,
|
|
constants.INTERFACE_CLASS_PLATFORM, 1, iface,
|
|
expect_errors=True)
|
|
self._create_vlan('mgmt', constants.NETWORK_TYPE_MGMT,
|
|
constants.INTERFACE_CLASS_PLATFORM, 2, iface,
|
|
expect_errors=True)
|
|
self._create_vlan('infra', constants.NETWORK_TYPE_INFRA,
|
|
constants.INTERFACE_CLASS_PLATFORM, 3, iface,
|
|
expect_errors=True)
|
|
self._create_vlan('data2', constants.NETWORK_TYPE_DATA,
|
|
constants.INTERFACE_CLASS_DATA,
|
|
5, iface,
|
|
datanetworks='group0-ext0',
|
|
expect_errors=False)
|
|
self._create_ethernet('sriov', constants.NETWORK_TYPE_PCI_SRIOV,
|
|
ifclass=constants.INTERFACE_CLASS_PCI_SRIOV,
|
|
datanetworks='group0-ext1',
|
|
expect_errors=False)
|
|
self._create_ethernet('pthru', constants.NETWORK_TYPE_PCI_PASSTHROUGH,
|
|
ifclass=constants.INTERFACE_CLASS_PCI_PASSTHROUGH,
|
|
datanetworks='group0-ext2',
|
|
expect_errors=False)
|
|
|
|
def setUp(self):
|
|
super(InterfaceCpeVlanOverDataEthernet, self).setUp()
|
|
|
|
|
|
class TestList(InterfaceTestCase):
|
|
|
|
def setUp(self):
|
|
super(TestList, self).setUp()
|
|
self.system = dbutils.create_test_isystem()
|
|
self.load = dbutils.create_test_load()
|
|
self.host = dbutils.create_test_ihost(forisystemid=self.system.id)
|
|
self.port = dbutils.create_test_ethernet_port(host_id=self.host.id)
|
|
|
|
def test_list_interface(self):
|
|
interface = dbutils.create_test_interface(forihostid='1')
|
|
data = self.get_json('/ihosts/%s/iinterfaces' % self.host['uuid'])
|
|
self.assertIn('ifname', data['iinterfaces'][0])
|
|
self.assertEqual(interface.uuid, data['iinterfaces'][0]["uuid"])
|
|
self.is_interface_equal(interface.as_dict(), data['iinterfaces'][0])
|
|
|
|
|
|
class TestPatch(InterfaceTestCase):
|
|
def setUp(self):
|
|
super(TestPatch, self).setUp()
|
|
self._create_host(constants.CONTROLLER)
|
|
self._create_host(constants.WORKER, admin=constants.ADMIN_LOCKED)
|
|
self._create_datanetworks()
|
|
|
|
def test_modify_ifname(self):
|
|
interface = dbutils.create_test_interface(forihostid='1')
|
|
response = self.patch_dict_json(
|
|
'%s' % self._get_path(interface.uuid),
|
|
ifname='new_name')
|
|
self.assertEqual('application/json', response.content_type)
|
|
self.assertEqual(http_client.OK, response.status_code)
|
|
self.assertEqual('new_name', response.json['ifname'])
|
|
|
|
def test_modify_mtu(self):
|
|
interface = dbutils.create_test_interface(forihostid='1')
|
|
response = self.patch_dict_json(
|
|
'%s' % self._get_path(interface.uuid),
|
|
imtu=1600)
|
|
self.assertEqual('application/json', response.content_type)
|
|
self.assertEqual(http_client.OK, response.status_code)
|
|
self.assertEqual(1600, response.json['imtu'])
|
|
|
|
def test_interface_usesmodify_success(self):
|
|
data_bond = self._create_bond('data', constants.NETWORK_TYPE_DATA,
|
|
constants.INTERFACE_CLASS_DATA,
|
|
datanetworks='group0-data0',
|
|
host=self.worker)
|
|
|
|
port, new_ethernet = self._create_ethernet(
|
|
'new', constants.NETWORK_TYPE_NONE, host=self.worker)
|
|
# Modify AE interface to add another port
|
|
uses = ','.join(data_bond['uses'])
|
|
patch_result = self.patch_dict_json(
|
|
'%s' % self._get_path(data_bond['uuid']),
|
|
usesmodify=uses + ',' + new_ethernet['uuid'])
|
|
self.assertEqual('application/json', patch_result.content_type)
|
|
self.assertEqual(http_client.OK, patch_result.status_code)
|
|
|
|
# Expected error: Interface MTU (%s) cannot be smaller than the interface
|
|
# MTU (%s) using this interface
|
|
def test_mtu_smaller_than_users(self):
|
|
port, lower_interface = self._create_ethernet(
|
|
'pxeboot', constants.NETWORK_TYPE_PXEBOOT, host=self.worker)
|
|
dbutils.create_test_interface(
|
|
forihostid='2',
|
|
ihost_uuid=self.worker.uuid,
|
|
ifname='data0',
|
|
networktype=constants.NETWORK_TYPE_DATA,
|
|
ifclass=constants.INTERFACE_CLASS_DATA,
|
|
iftype=constants.INTERFACE_TYPE_ETHERNET,
|
|
datanetworks='group0-data0',
|
|
aemode='balanced',
|
|
txhashpolicy='layer2',
|
|
uses=['pxeboot'],
|
|
imtu=1600)
|
|
response = self.patch_dict_json(
|
|
'%s' % self._get_path(lower_interface['uuid']), imtu=1400,
|
|
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 error: VLAN MTU ___ cannot be larger than MTU of underlying
|
|
# interface ___
|
|
def test_vlan_mtu_smaller_than_users(self):
|
|
port, lower_interface = self._create_ethernet(
|
|
'pxeboot', constants.NETWORK_TYPE_PXEBOOT, host=self.worker)
|
|
upper = dbutils.create_test_interface(
|
|
forihostid='2',
|
|
ihost_uuid=self.worker.uuid,
|
|
ifname='data0',
|
|
networktype=constants.NETWORK_TYPE_DATA,
|
|
ifclass=constants.INTERFACE_CLASS_DATA,
|
|
iftype=constants.INTERFACE_TYPE_VLAN,
|
|
vlan_id=100,
|
|
datanetworks='group0-ext0',
|
|
aemode='balanced',
|
|
txhashpolicy='layer2',
|
|
uses=['pxeboot'],
|
|
imtu=1500)
|
|
response = self.patch_dict_json(
|
|
'%s' % self._get_path(upper['uuid']), imtu=1800,
|
|
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'])
|
|
|
|
# No longer requires setting the network type back to none
|
|
# Expected error: The network type of an interface cannot be changed without
|
|
# first being reset back to none
|
|
# def test_invalid_change_networktype(self):
|
|
# port, interface = self._create_ethernet('oam',
|
|
# constants.NETWORK_TYPE_OAM)
|
|
# response = self.patch_dict_json(
|
|
# '%s' % self._get_path(interface['uuid']),
|
|
# networktype=constants.NETWORK_TYPE_MGMT, expect_errors=True)
|
|
# self.assertEqual(http_client.BAD_REQUEST, response.status_int)
|
|
# self.assertEqual('application/json', response.content_type)
|
|
# self.assertTrue(response.json['error_message'])
|
|
|
|
|
|
class TestPost(InterfaceTestCase):
|
|
def setUp(self):
|
|
super(TestPost, self).setUp()
|
|
self._create_host(constants.CONTROLLER)
|
|
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):
|
|
self._create_bond('pthru', constants.NETWORK_TYPE_PCI_PASSTHROUGH,
|
|
ifclass=constants.INTERFACE_CLASS_PCI_PASSTHROUGH,
|
|
host=self.worker, expect_errors=True)
|
|
|
|
# Expected error: The ___ network type is only supported on nodes supporting
|
|
# worker functions
|
|
def test_invalid_network_type_on_nonworker(self):
|
|
self._create_ethernet('data0', constants.NETWORK_TYPE_DATA,
|
|
ifclass=constants.INTERFACE_CLASS_DATA,
|
|
datanetworks='group0-ext0',
|
|
expect_errors=True)
|
|
|
|
# Expected error: Interface name cannot be whitespace.
|
|
def test_invalid_whitespace_interface_name(self):
|
|
self._create_ethernet(' ', constants.NETWORK_TYPE_DATA,
|
|
ifclass=constants.INTERFACE_CLASS_DATA,
|
|
datanetworks='group0-ext0',
|
|
expect_errors=True)
|
|
|
|
# Expected error: Interface name must be in lower case.
|
|
def test_invalid_uppercase_interface_name(self):
|
|
self._create_ethernet('miXedCaSe', constants.NETWORK_TYPE_DATA,
|
|
ifclass=constants.INTERFACE_CLASS_DATA,
|
|
datanetworks='group0-ext0',
|
|
expect_errors=True)
|
|
|
|
# Expected error: Cannot use special characters in interface name.
|
|
def test_invalid_character_interface_name(self):
|
|
self._create_ethernet('bad-name', constants.NETWORK_TYPE_DATA,
|
|
ifclass=constants.INTERFACE_CLASS_DATA,
|
|
datanetworks='group0-ext0',
|
|
expect_errors=True)
|
|
|
|
# Expected error: Interface ___ has name length greater than 10.
|
|
def test_invalid_interface_name_length(self):
|
|
self._create_ethernet('0123456789a', constants.NETWORK_TYPE_OAM,
|
|
expect_errors=True)
|
|
|
|
# Expected message: Name must be unique
|
|
def test_create_duplicate_interface_name(self):
|
|
self._create_ethernet('data0', constants.NETWORK_TYPE_DATA,
|
|
ifclass=constants.INTERFACE_CLASS_DATA,
|
|
datanetworks='group0-data0',
|
|
host=self.worker)
|
|
self._create_ethernet('data0', constants.NETWORK_TYPE_DATA,
|
|
ifclass=constants.INTERFACE_CLASS_DATA,
|
|
datanetworks='group0-ext0',
|
|
host=self.worker,
|
|
expect_errors=True)
|
|
|
|
def test_ipv4_mode_valid(self):
|
|
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,
|
|
ipv4_pool=self.address_pool1.uuid)
|
|
self._post_and_check_success(ndict)
|
|
|
|
# Expected error: Address mode attributes only supported on
|
|
# mgmt, infra, data, data-vrs interfaces
|
|
def test_ipv4_mode_networktype_invalid(self):
|
|
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,
|
|
ipv6_mode=constants.IPV6_STATIC,
|
|
ipv4_pool=self.address_pool1.uuid,
|
|
ipv6_pool=self.address_pool2.uuid)
|
|
self._post_and_check_failure(ndict)
|
|
|
|
# Expected error: Infrastructure static addressing is configured; IPv4
|
|
# address mode must be static
|
|
def test_ipv4_mode_infra_invalid(self):
|
|
ndict = dbutils.post_get_test_interface(
|
|
ihost_uuid=self.controller.uuid,
|
|
ifname='name',
|
|
networktype=constants.NETWORK_TYPE_INFRA,
|
|
networks=['2'],
|
|
ifclass=constants.INTERFACE_CLASS_PLATFORM,
|
|
iftype=constants.INTERFACE_TYPE_ETHERNET,
|
|
ipv4_mode=constants.IPV4_DISABLED,
|
|
ipv6_mode=constants.IPV6_DISABLED,
|
|
ipv4_pool=self.address_pool1.uuid)
|
|
self._post_and_check_failure(ndict)
|
|
|
|
# Expected error: Specifying an IPv4 address pool requires setting the
|
|
# address mode to pool
|
|
def test_ipv4_mode_invalid(self):
|
|
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,
|
|
ipv4_pool=self.address_pool1.uuid)
|
|
self._post_and_check_failure(ndict)
|
|
|
|
# Expected error: Specifying an IPv6 address pool requires setting the
|
|
# address mode to pool
|
|
def test_ipv6_mode_invalid(self):
|
|
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,
|
|
ipv6_mode=constants.IPV6_DISABLED,
|
|
ipv6_pool=self.address_pool1.uuid)
|
|
self._post_and_check_failure(ndict)
|
|
|
|
# Expected error: IPv4 address pool name not specified
|
|
def test_ipv4_mode_no_pool_invalid(self):
|
|
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,
|
|
ipv6_mode=constants.IPV6_POOL)
|
|
self._post_and_check_failure(ndict)
|
|
|
|
# Expected error: IPv6 address pool name not specified
|
|
def test_ipv6_mode_no_pool_invalid(self):
|
|
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,
|
|
ipv6_mode=constants.IPV6_POOL,
|
|
ipv4_pool=self.address_pool_v6.uuid)
|
|
self._post_and_check_failure(ndict)
|
|
|
|
# Expected error: Address pool IP family does not match requested family
|
|
def test_ipv4_pool_family_mismatch_invalid(self):
|
|
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,
|
|
ipv6_mode=constants.IPV6_POOL,
|
|
ipv4_pool=self.address_pool_v6.uuid,
|
|
ipv6_pool=self.address_pool_v6.uuid)
|
|
self._post_and_check_failure(ndict)
|
|
|
|
# Expected error: Address pool IP family does not match requested family
|
|
def test_ipv6_pool_family_mismatch_invalid(self):
|
|
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,
|
|
ipv6_mode=constants.IPV6_POOL,
|
|
ipv4_pool=self.address_pool1.uuid,
|
|
ipv6_pool=self.address_pool1.uuid)
|
|
self._post_and_check_failure(ndict)
|
|
|
|
# Expected error: Device interface type must be 'aggregated ethernet' or
|
|
# 'vlan' or 'ethernet'.
|
|
def test_aemode_invalid_iftype(self):
|
|
ndict = dbutils.post_get_test_interface(
|
|
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',
|
|
txhashpolicy='layer2')
|
|
self._post_and_check_failure(ndict)
|
|
|
|
# Expected error: Device interface with interface type 'aggregated ethernet'
|
|
# in ___ mode should not specify a Tx Hash Policy.
|
|
def test_aemode_no_txhash(self):
|
|
ndict = dbutils.post_get_test_interface(
|
|
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',
|
|
txhashpolicy='layer2')
|
|
self._post_and_check_failure(ndict)
|
|
|
|
# Device interface with network type ___, and interface type
|
|
# 'aggregated ethernet' must have a Tx Hash Policy of 'layer2'.
|
|
def test_aemode_invalid_txhash(self):
|
|
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',
|
|
txhashpolicy='layer2+3')
|
|
self._post_and_check_failure(ndict)
|
|
|
|
# Expected error: Device interface with interface type 'aggregated ethernet'
|
|
# in 'balanced' or '802.3ad' mode require a valid Tx Hash Policy
|
|
def test_aemode_invalid_txhash_none(self):
|
|
ndict = dbutils.post_get_test_interface(
|
|
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',
|
|
txhashpolicy=None)
|
|
self._post_and_check_failure(ndict)
|
|
|
|
ndict = dbutils.post_get_test_interface(
|
|
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'.
|
|
def test_aemode_invalid_data(self):
|
|
ndict = dbutils.post_get_test_interface(
|
|
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):
|
|
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_infra(self):
|
|
ndict = dbutils.post_get_test_interface(
|
|
ihost_uuid=self.worker.uuid,
|
|
ifname='name',
|
|
networktype=constants.NETWORK_TYPE_INFRA,
|
|
networks=['2'],
|
|
ifclass=constants.INTERFACE_CLASS_PLATFORM,
|
|
iftype=constants.INTERFACE_TYPE_AE,
|
|
aemode='bad_aemode',
|
|
txhashpolicy='layer2')
|
|
self._post_and_check_failure(ndict)
|
|
|
|
# Expected error: Interface ___ does not have associated infra interface
|
|
# on controller.
|
|
def test_no_infra_on_controller(self):
|
|
ndict = dbutils.post_get_test_interface(
|
|
ihost_uuid=self.worker.uuid,
|
|
ifname='name',
|
|
networktype=constants.NETWORK_TYPE_INFRA,
|
|
networks=['2'],
|
|
ifclass=constants.INTERFACE_CLASS_PLATFORM,
|
|
iftype=constants.INTERFACE_TYPE_ETHERNET,
|
|
aemode='balanced',
|
|
txhashpolicy='layer2')
|
|
self._post_and_check_failure(ndict)
|
|
|
|
def test_setting_mgmt_mtu_allowed(self):
|
|
ndict = dbutils.post_get_test_interface(
|
|
ihost_uuid=self.controller.uuid,
|
|
ifname='mgmt0',
|
|
networktype=constants.NETWORK_TYPE_MGMT,
|
|
networks=['1'],
|
|
ifclass=constants.INTERFACE_CLASS_PLATFORM,
|
|
iftype=constants.INTERFACE_TYPE_ETHERNET,
|
|
imtu=1600)
|
|
self._post_and_check_success(ndict)
|
|
|
|
def test_setting_infra_mtu_allowed(self):
|
|
ndict = dbutils.post_get_test_interface(
|
|
ihost_uuid=self.controller.uuid,
|
|
ifname='infra0',
|
|
networktype=constants.NETWORK_TYPE_INFRA,
|
|
networks=['2'],
|
|
ifclass=constants.INTERFACE_CLASS_PLATFORM,
|
|
iftype=constants.INTERFACE_TYPE_ETHERNET,
|
|
imtu=1600)
|
|
self._post_and_check_success(ndict)
|
|
|
|
# Expected message: Interface eth0 is already used by another AE interface
|
|
# bond0
|
|
def test_create_bond_invalid_overlap_ae(self):
|
|
bond_iface = self._create_worker_bond('bond0',
|
|
constants.NETWORK_TYPE_DATA,
|
|
constants.INTERFACE_CLASS_DATA,
|
|
datanetworks='group0-data0')
|
|
port, iface1 = self._create_ethernet()
|
|
|
|
ndict = dbutils.post_get_test_interface(
|
|
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',
|
|
txhashpolicy='layer2',
|
|
uses=[bond_iface['uses'][0], iface1['uuid']])
|
|
self._post_and_check_failure(ndict)
|
|
|
|
# Expected message: VLAN id must be between 1 and 4094.
|
|
def test_create_invalid_vlan_id(self):
|
|
self._create_worker_vlan('vlan0', constants.NETWORK_TYPE_DATA,
|
|
ifclass=constants.INTERFACE_CLASS_DATA,
|
|
vlan_id=4095,
|
|
datanetworks='group0-ext0',
|
|
expect_errors=True)
|
|
|
|
# Expected message: Interface eth0 is already used by another VLAN
|
|
# interface vlan0
|
|
def test_create_bond_invalid_overlap_vlan(self):
|
|
vlan_iface = self._create_worker_vlan(
|
|
'vlan0',
|
|
constants.NETWORK_TYPE_DATA,
|
|
ifclass=constants.INTERFACE_CLASS_DATA,
|
|
vlan_id=10, datanetworks='group0-ext0')
|
|
port, iface1 = self._create_ethernet()
|
|
|
|
ndict = dbutils.post_get_test_interface(
|
|
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',
|
|
txhashpolicy='layer2',
|
|
uses=[vlan_iface['uses'][0], iface1['uuid']])
|
|
self._post_and_check_failure(ndict)
|
|
|
|
# Expected message: Can only have one interface for vlan type.
|
|
def test_create_vlan_invalid_uses(self):
|
|
bond_iface = self._create_worker_bond('bond0',
|
|
constants.NETWORK_TYPE_DATA,
|
|
constants.INTERFACE_CLASS_DATA,
|
|
datanetworks='group0-data0')
|
|
port, iface1 = self._create_ethernet()
|
|
|
|
ndict = dbutils.post_get_test_interface(
|
|
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',
|
|
txhashpolicy='layer2',
|
|
uses=[bond_iface['uses'][0], iface1['uuid']])
|
|
self._post_and_check_failure(ndict)
|
|
|
|
# Expected message: VLAN interfaces cannot be created over existing VLAN
|
|
# interfaces
|
|
def test_create_invalid_vlan_over_vlan(self):
|
|
vlan_iface = self._create_worker_vlan(
|
|
'vlan1', constants.NETWORK_TYPE_DATA,
|
|
constants.INTERFACE_CLASS_DATA, 1,
|
|
datanetworks='group0-ext0')
|
|
self._create_worker_vlan('vlan2',
|
|
constants.NETWORK_TYPE_DATA,
|
|
constants.INTERFACE_CLASS_DATA,
|
|
vlan_id=2,
|
|
lower_iface=vlan_iface,
|
|
datanetworks='group0-ext1',
|
|
expect_errors=True)
|
|
|
|
# Expected message: data VLAN cannot be created over a LAG interface with
|
|
# network type pxeboot
|
|
def test_create_data_vlan_over_pxeboot_lag(self):
|
|
bond_iface = self._create_worker_bond(
|
|
'pxeboot', constants.NETWORK_TYPE_PXEBOOT,
|
|
constants.INTERFACE_CLASS_PLATFORM)
|
|
self._create_worker_vlan(
|
|
'vlan2',
|
|
constants.NETWORK_TYPE_DATA, constants.INTERFACE_CLASS_DATA, 2,
|
|
lower_iface=bond_iface, datanetworks='group0-ext1',
|
|
expect_errors=True)
|
|
|
|
# Expected message: data VLAN cannot be created over a LAG interface with
|
|
# network type mgmt
|
|
def test_create_data_vlan_over_mgmt_lag(self):
|
|
bond_iface = self._create_worker_bond(
|
|
'mgmt', constants.NETWORK_TYPE_MGMT,
|
|
constants.INTERFACE_CLASS_PLATFORM)
|
|
self._create_worker_vlan(
|
|
'vlan2', constants.NETWORK_TYPE_DATA,
|
|
constants.INTERFACE_CLASS_DATA, 2,
|
|
lower_iface=bond_iface, datanetworks='group0-ext1',
|
|
expect_errors=True)
|
|
|
|
# Expected message: mgmt VLAN cannot be created over a LAG interface with
|
|
# network type data
|
|
def test_create_mgmt_vlan_over_data_lag(self):
|
|
bond_iface = self._create_worker_bond(
|
|
'data', constants.NETWORK_TYPE_DATA,
|
|
constants.INTERFACE_CLASS_DATA, datanetworks='group0-ext1')
|
|
self._create_worker_vlan(
|
|
'mgmt', constants.NETWORK_TYPE_MGMT,
|
|
constants.INTERFACE_CLASS_PLATFORM, 2,
|
|
lower_iface=bond_iface, datanetworks='group0-ext1',
|
|
expect_errors=True)
|
|
|
|
# Expected message:
|
|
# Data network(s) not supported for non-data interfaces.
|
|
def test_create_nondata_data_network(self):
|
|
self._create_worker_bond(
|
|
'pxeboot', constants.NETWORK_TYPE_PXEBOOT,
|
|
constants.INTERFACE_CLASS_PLATFORM,
|
|
datanetworks='group0-data0', expect_errors=True)
|
|
|
|
# Expected message: Name must be unique
|
|
def test_create_invalid_ae_name(self):
|
|
self._create_ethernet('enp0s9', constants.NETWORK_TYPE_NONE)
|
|
self._create_bond('enp0s9', constants.NETWORK_TYPE_MGMT,
|
|
constants.INTERFACE_CLASS_PLATFORM,
|
|
expect_errors=True)
|
|
|
|
# Expected message:
|
|
# Only pxeboot,mgmt,infra network types can be combined on a single
|
|
# interface
|
|
def test_create_invalid_oam_data_ethernet(self):
|
|
self._create_ethernet('shared',
|
|
networktype=[constants.NETWORK_TYPE_OAM,
|
|
constants.NETWORK_TYPE_DATA],
|
|
expect_errors=True)
|
|
|
|
# Expected message:
|
|
# Only pxeboot,mgmt,infra network types can be combined on a single
|
|
# interface
|
|
def test_create_invalid_mgmt_data_ethernet(self):
|
|
self._create_ethernet('shared',
|
|
networktype=[constants.NETWORK_TYPE_MGMT,
|
|
constants.NETWORK_TYPE_DATA],
|
|
datanetworks='group0-data0',
|
|
host=self.worker,
|
|
expect_errors=True)
|
|
|
|
# Expected message:
|
|
# Only pxeboot,mgmt,infra network types can be combined on a single
|
|
# interface
|
|
def test_create_invalid_pxeboot_data_ethernet(self):
|
|
self._create_ethernet('shared',
|
|
networktype=[constants.NETWORK_TYPE_DATA,
|
|
constants.NETWORK_TYPE_PXEBOOT],
|
|
datanetworks='group0-data0',
|
|
host=self.worker,
|
|
expect_errors=True)
|
|
|
|
|
|
class TestCpePost(InterfaceTestCase):
|
|
def setUp(self):
|
|
super(TestCpePost, self).setUp()
|
|
self._create_host(constants.CONTROLLER, constants.WORKER,
|
|
admin=constants.ADMIN_LOCKED)
|
|
self._create_datanetworks()
|
|
|
|
# Expected message:
|
|
# Network type list may only contain at most one type
|
|
def test_create_ae_with_networktypes(self):
|
|
self._create_bond('bond0',
|
|
networktype=[constants.NETWORK_TYPE_DATA,
|
|
constants.NETWORK_TYPE_PXEBOOT],
|
|
datanetworks='group0-data0', expect_errors=True)
|
|
|
|
# Expected message:
|
|
# Network type list may only contain at most one type
|
|
def test_create_invalid_infra_data_ae(self):
|
|
self._create_bond('shared',
|
|
networktype=[constants.NETWORK_TYPE_INFRA,
|
|
constants.NETWORK_TYPE_DATA],
|
|
datanetworks='group0-data0',
|
|
expect_errors=True)
|
|
|
|
# Expected message: oam VLAN cannot be created over an interface with
|
|
# network type data
|
|
def test_create_oam_vlan_over_data_lag(self):
|
|
bond_iface = self._create_bond(
|
|
'data', constants.NETWORK_TYPE_DATA,
|
|
constants.INTERFACE_CLASS_DATA, datanetworks='group0-ext1')
|
|
self._create_vlan(
|
|
'oam', constants.NETWORK_TYPE_OAM,
|
|
constants.INTERFACE_CLASS_PLATFORM, 2,
|
|
lower_iface=bond_iface, datanetworks='group0-ext1',
|
|
expect_errors=True)
|
|
|
|
# Expected message: infra VLAN cannot be created over an interface with
|
|
# network type data
|
|
def test_create_infra_vlan_over_data_lag(self):
|
|
bond_iface = self._create_bond(
|
|
'data', constants.NETWORK_TYPE_DATA,
|
|
constants.INTERFACE_CLASS_DATA, datanetworks='group0-ext1')
|
|
self._create_vlan(
|
|
'infra', constants.NETWORK_TYPE_INFRA,
|
|
constants.INTERFACE_CLASS_PLATFORM, 2,
|
|
lower_iface=bond_iface, datanetworks='group0-ext1',
|
|
expect_errors=True)
|
|
|
|
# Expected message: mgmt VLAN cannot be created over an interface with
|
|
# network type data
|
|
def test_create_mgmt_vlan_over_data_ethernet(self):
|
|
port, iface = self._create_ethernet(
|
|
'data', constants.NETWORK_TYPE_DATA,
|
|
constants.INTERFACE_CLASS_DATA, datanetworks='group0-ext1')
|
|
self._create_vlan(
|
|
'mgmt', constants.NETWORK_TYPE_MGMT,
|
|
constants.INTERFACE_CLASS_PLATFORM, 2,
|
|
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)
|
|
self._create_vlan('vlan1', constants.NETWORK_TYPE_DATA,
|
|
constants.INTERFACE_CLASS_DATA, vlan_id=1,
|
|
lower_iface=iface, datanetworks='group0-ext0')
|
|
self._create_vlan('vlan2', constants.NETWORK_TYPE_DATA,
|
|
constants.INTERFACE_CLASS_DATA, vlan_id=1,
|
|
lower_iface=iface, datanetworks='group0-ext1',
|
|
expect_errors=True)
|
|
|
|
# Expected message: Network type list may only contain at most one type
|
|
def test_create_invalid_vlan_multiple_networktype(self):
|
|
port, lower = self._create_ethernet('eth1', constants.NETWORK_TYPE_NONE)
|
|
self._create_vlan('vlan2',
|
|
networktype=[constants.NETWORK_TYPE_MGMT,
|
|
constants.NETWORK_TYPE_DATA],
|
|
ifclass=constants.INTERFACE_CLASS_PLATFORM,
|
|
vlan_id=2, lower_iface=lower, expect_errors=True)
|
|
|
|
# Expected message: VLAN interfaces cannot have a network type of 'none'
|
|
def test_create_invalid_vlan_networktype_none(self):
|
|
port, lower = self._create_ethernet('eth1', constants.NETWORK_TYPE_NONE)
|
|
self._create_vlan('vlan2', networktype='none',
|
|
ifclass=constants.INTERFACE_CLASS_NONE,
|
|
vlan_id=2, lower_iface=lower, expect_errors=True)
|
|
|
|
# Expected error: VLAN based provider network group0-data0 cannot be
|
|
# 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,
|
|
ifclass=constants.INTERFACE_CLASS_DATA,
|
|
datanetworks='group0-data0',
|
|
vlan_id=2, lower_iface=lower, expect_errors=True)
|
|
|
|
@testtools.skip("deprecate neutron bind interface")
|
|
@mock.patch.object(dbsql_api.Connection, 'iinterface_destroy')
|
|
@mock.patch.object(rpcapi.ConductorAPI, 'neutron_bind_interface')
|
|
def test_create_neutron_bind_failed(self, mock_neutron_bind_interface,
|
|
mock_iinterface_destroy):
|
|
self._create_ethernet('enp0s9', constants.NETWORK_TYPE_NONE)
|
|
mock_neutron_bind_interface.side_effect = [
|
|
None,
|
|
rpc_common.RemoteError(
|
|
mock.Mock(status=404), 'not found')
|
|
]
|
|
ndict = dbutils.post_get_test_interface(
|
|
forihostid=self.controller.id,
|
|
ihost_uuid=self.controller.uuid,
|
|
datanetworks='group0-ext1',
|
|
ifname='data1',
|
|
networktype=constants.NETWORK_TYPE_DATA,
|
|
ifclass=constants.INTERFACE_CLASS_DATA,
|
|
iftype=constants.INTERFACE_TYPE_ETHERNET,
|
|
uses=['enp0s9'])
|
|
self._post_and_check_failure(ndict)
|
|
mock_neutron_bind_interface.assert_called_with(
|
|
mock.ANY, mock.ANY, mock.ANY, constants.NETWORK_TYPE_DATA,
|
|
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):
|
|
self._create_ethernet('data0',
|
|
networktype=constants.NETWORK_TYPE_DATA,
|
|
ifclass=constants.INTERFACE_CLASS_DATA,
|
|
datanetworks='group0-data0')
|
|
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)
|
|
|
|
|
|
class TestCpePatch(InterfaceTestCase):
|
|
def setUp(self):
|
|
super(TestCpePatch, self).setUp()
|
|
self._create_host(constants.CONTROLLER, constants.WORKER,
|
|
admin=constants.ADMIN_LOCKED)
|
|
self._create_datanetworks()
|
|
|
|
def test_create_invalid_infra_data_ethernet(self):
|
|
self._create_ethernet('shared',
|
|
networktype=[constants.NETWORK_TYPE_INFRA,
|
|
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):
|
|
port, interface = self._create_ethernet(
|
|
'data0', networktype=constants.NETWORK_TYPE_DATA,
|
|
ifclass=constants.INTERFACE_CLASS_DATA,
|
|
datanetworks='group0-data0')
|
|
|
|
mock_neutron_bind_interface.side_effect = [
|
|
None,
|
|
rpc_common.RemoteError(
|
|
mock.Mock(return_value={'status': 404}), 'not found'),
|
|
None]
|
|
|
|
patch_result = self.patch_dict_json(
|
|
'%s' % self._get_path(interface['uuid']),
|
|
imtu=2000, expect_errors=True)
|
|
self.assertEqual(http_client.BAD_REQUEST, patch_result.status_int)
|
|
self.assertEqual('application/json', patch_result.content_type)
|
|
self.assertTrue(patch_result.json['error_message'])
|
|
|
|
# Expected error: Value for number of SR-IOV VFs must be > 0.
|
|
def test_invalid_sriov_numvfs(self):
|
|
port, interface = self._create_ethernet('eth0',
|
|
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')
|
|
dbutils.create_test_ethernet_port(
|
|
id=1, name='eth1', host_id=1, interface_id=interface.id,
|
|
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)
|
|
self.assertEqual(http_client.BAD_REQUEST, response.status_int)
|
|
self.assertEqual('application/json', response.content_type)
|
|
|
|
# Expected error: The interface support a maximum of ___ VFs
|
|
def test_invalid_sriov_exceeded_totalvfs(self):
|
|
interface = dbutils.create_test_interface(forihostid='1')
|
|
dbutils.create_test_ethernet_port(
|
|
id=1, name='eth1', host_id=1, interface_id=interface.id,
|
|
pciaddr='0000:00:00.11', dev_id=0, sriov_totalvfs=1, sriov_numvfs=1,
|
|
driver=None)
|
|
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=2,
|
|
expect_errors=True)
|
|
self.assertEqual(http_client.BAD_REQUEST, response.status_int)
|
|
self.assertEqual('application/json', response.content_type)
|
|
|
|
# Expected error: Corresponding port has invalid driver
|
|
def test_invalid_driver_for_sriov(self):
|
|
interface = dbutils.create_test_interface(forihostid='1')
|
|
dbutils.create_test_ethernet_port(
|
|
id=1, name='eth1', host_id=1, interface_id=interface.id,
|
|
pciaddr='0000:00:00.11', dev_id=0, sriov_totalvfs=1, sriov_numvfs=1,
|
|
driver=None)
|
|
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)
|
|
self.assertEqual(http_client.BAD_REQUEST, response.status_int)
|
|
self.assertEqual('application/json', response.content_type)
|