Merge "tests for port-resource-request"
This commit is contained in:
commit
201903d8b8
@ -46,6 +46,7 @@
|
|||||||
- network-ip-availability
|
- network-ip-availability
|
||||||
- network_availability_zone
|
- network_availability_zone
|
||||||
- pagination
|
- pagination
|
||||||
|
- port-resource-request
|
||||||
- port-mac-address-regenerate
|
- port-mac-address-regenerate
|
||||||
- port-security
|
- port-security
|
||||||
- port-security-groups-filtering
|
- port-security-groups-filtering
|
||||||
@ -127,6 +128,7 @@
|
|||||||
agent_availability_zone: nova
|
agent_availability_zone: nova
|
||||||
image_is_advanced: true
|
image_is_advanced: true
|
||||||
available_type_drivers: flat,geneve,vlan,gre,local,vxlan
|
available_type_drivers: flat,geneve,vlan,gre,local,vxlan
|
||||||
|
provider_net_base_segm_id: 1
|
||||||
irrelevant-files: &tempest-irrelevant-files
|
irrelevant-files: &tempest-irrelevant-files
|
||||||
- ^(test-|)requirements.txt$
|
- ^(test-|)requirements.txt$
|
||||||
- ^releasenotes/.*$
|
- ^releasenotes/.*$
|
||||||
|
@ -14,11 +14,17 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import netaddr
|
import netaddr
|
||||||
|
import six
|
||||||
|
|
||||||
|
from neutron_lib import constants as const
|
||||||
from tempest.common import utils
|
from tempest.common import utils
|
||||||
|
from tempest.lib.common.utils import data_utils
|
||||||
from tempest.lib import decorators
|
from tempest.lib import decorators
|
||||||
|
|
||||||
from neutron_tempest_plugin.api import base
|
from neutron_tempest_plugin.api import base
|
||||||
|
from neutron_tempest_plugin import config
|
||||||
|
|
||||||
|
CONF = config.CONF
|
||||||
|
|
||||||
|
|
||||||
class PortTestCasesAdmin(base.BaseAdminNetworkTest):
|
class PortTestCasesAdmin(base.BaseAdminNetworkTest):
|
||||||
@ -58,3 +64,126 @@ class PortTestCasesAdmin(base.BaseAdminNetworkTest):
|
|||||||
new_mac = body['port']['mac_address']
|
new_mac = body['port']['mac_address']
|
||||||
self.assertNotEqual(current_mac, new_mac)
|
self.assertNotEqual(current_mac, new_mac)
|
||||||
self.assertTrue(netaddr.valid_mac(new_mac))
|
self.assertTrue(netaddr.valid_mac(new_mac))
|
||||||
|
|
||||||
|
|
||||||
|
class PortTestCasesResourceRequest(base.BaseAdminNetworkTest):
|
||||||
|
|
||||||
|
required_extensions = ['port-resource-request',
|
||||||
|
'qos',
|
||||||
|
'qos-bw-minimum-ingress']
|
||||||
|
|
||||||
|
EGRESS_KBPS = 1000
|
||||||
|
INGRESS_KBPS = 2000
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def skip_checks(cls):
|
||||||
|
super(PortTestCasesResourceRequest, cls).skip_checks()
|
||||||
|
if not config.CONF.neutron_plugin_options.provider_vlans:
|
||||||
|
msg = "Skipped as provider VLANs are not available in config"
|
||||||
|
raise cls.skipException(msg)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def resource_setup(cls):
|
||||||
|
super(PortTestCasesResourceRequest, cls).resource_setup()
|
||||||
|
|
||||||
|
cls.vnic_type = 'normal'
|
||||||
|
|
||||||
|
# Note(lajoskatona): to avoid creating provider network use vxlan
|
||||||
|
# as provider network type:
|
||||||
|
cls.network = cls.create_network(provider_network_type='vxlan')
|
||||||
|
cls.physnet_name = CONF.neutron_plugin_options.provider_vlans[0]
|
||||||
|
base_segm = CONF.neutron_plugin_options.provider_net_base_segm_id
|
||||||
|
cls.prov_network = cls.create_provider_network(
|
||||||
|
physnet_name=cls.physnet_name, start_segmentation_id=base_segm)
|
||||||
|
|
||||||
|
def _create_qos_policy_and_port(self, network, vnic_type,
|
||||||
|
network_policy=False):
|
||||||
|
qos_policy = self.create_qos_policy(
|
||||||
|
name=data_utils.rand_name('test_policy'), shared=True)
|
||||||
|
self.create_qos_minimum_bandwidth_rule(qos_policy['id'],
|
||||||
|
self.EGRESS_KBPS,
|
||||||
|
const.EGRESS_DIRECTION)
|
||||||
|
self.create_qos_minimum_bandwidth_rule(qos_policy['id'],
|
||||||
|
self.INGRESS_KBPS,
|
||||||
|
const.INGRESS_DIRECTION)
|
||||||
|
|
||||||
|
port_policy_id = qos_policy['id'] if not network_policy else None
|
||||||
|
port_kwargs = {
|
||||||
|
'qos_policy_id': port_policy_id,
|
||||||
|
'binding:vnic_type': vnic_type
|
||||||
|
}
|
||||||
|
|
||||||
|
if network_policy:
|
||||||
|
self.admin_client.update_network(network['id'],
|
||||||
|
qos_policy_id=qos_policy['id'])
|
||||||
|
|
||||||
|
port_id = self.create_port(network, **port_kwargs)['id']
|
||||||
|
return self.admin_client.show_port(port_id)['port']
|
||||||
|
|
||||||
|
def _assert_resource_request(self, port, vnic_type):
|
||||||
|
self.assertIn('resource_request', port)
|
||||||
|
vnic_trait = 'CUSTOM_VNIC_TYPE_%s' % vnic_type.upper()
|
||||||
|
physnet_trait = 'CUSTOM_PHYSNET_%s' % self.physnet_name.upper()
|
||||||
|
six.assertCountEqual(self, [physnet_trait, vnic_trait],
|
||||||
|
port['resource_request']['required'])
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
{'NET_BW_EGR_KILOBIT_PER_SEC': self.EGRESS_KBPS,
|
||||||
|
'NET_BW_IGR_KILOBIT_PER_SEC': self.INGRESS_KBPS},
|
||||||
|
port['resource_request']['resources']
|
||||||
|
)
|
||||||
|
|
||||||
|
@decorators.idempotent_id('ebb86dc4-716c-4558-8516-6dfc4a67601f')
|
||||||
|
def test_port_resource_request(self):
|
||||||
|
port = self._create_qos_policy_and_port(
|
||||||
|
network=self.prov_network, vnic_type=self.vnic_type)
|
||||||
|
port_id = port['id']
|
||||||
|
|
||||||
|
self._assert_resource_request(port, self.vnic_type)
|
||||||
|
|
||||||
|
# Note(lajoskatona): port-resource-request is an admin only feature,
|
||||||
|
# so test if non-admin user can't see the new field.
|
||||||
|
port = self.client.show_port(port_id)['port']
|
||||||
|
self.assertNotIn('resource_request', port)
|
||||||
|
|
||||||
|
self.update_port(port, **{'qos_policy_id': None})
|
||||||
|
port = self.admin_client.show_port(port_id)['port']
|
||||||
|
self.assertIsNone(port['resource_request'])
|
||||||
|
|
||||||
|
@decorators.idempotent_id('10b3308b-d8a2-459b-9b89-a146863c357f')
|
||||||
|
def test_port_resource_request_no_provider_net(self):
|
||||||
|
port = self._create_qos_policy_and_port(
|
||||||
|
network=self.network, vnic_type=self.vnic_type)
|
||||||
|
|
||||||
|
self.assertIn('resource_request', port)
|
||||||
|
self.assertIsNone(port['resource_request'])
|
||||||
|
|
||||||
|
@decorators.idempotent_id('0eeb6ffa-9a7a-40b5-83dd-dbdcd67e2e64')
|
||||||
|
def test_port_resource_request_empty(self):
|
||||||
|
qos_policy = self.create_qos_policy(
|
||||||
|
name=data_utils.rand_name('test_policy'), shared=True)
|
||||||
|
|
||||||
|
# Note(lajoskatona): Add a non-minimum-bandwidth-rule to the policy
|
||||||
|
# to make sure that the resource request is not filled with it.
|
||||||
|
self.create_qos_bandwidth_limit_rule(qos_policy['id'],
|
||||||
|
self.EGRESS_KBPS, 800,
|
||||||
|
const.EGRESS_DIRECTION)
|
||||||
|
|
||||||
|
port_kwargs = {
|
||||||
|
'qos_policy_id': qos_policy['id'],
|
||||||
|
'binding:vnic_type': self.vnic_type
|
||||||
|
}
|
||||||
|
|
||||||
|
port_id = self.create_port(self.prov_network, **port_kwargs)['id']
|
||||||
|
port = self.admin_client.show_port(port_id)['port']
|
||||||
|
|
||||||
|
self.assertIn('resource_request', port)
|
||||||
|
self.assertIsNone(port['resource_request'])
|
||||||
|
|
||||||
|
@decorators.idempotent_id('b6c34ae4-44c8-47f0-86de-7ef9866fa000')
|
||||||
|
def test_port_resource_request_inherited_policy(self):
|
||||||
|
port = self._create_qos_policy_and_port(
|
||||||
|
network=self.prov_network, vnic_type=self.vnic_type,
|
||||||
|
network_policy=True)
|
||||||
|
|
||||||
|
self._assert_resource_request(port, self.vnic_type)
|
||||||
|
@ -14,10 +14,13 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import functools
|
import functools
|
||||||
|
import itertools
|
||||||
import math
|
import math
|
||||||
|
import time
|
||||||
|
|
||||||
import netaddr
|
import netaddr
|
||||||
from neutron_lib import constants as const
|
from neutron_lib import constants as const
|
||||||
|
from oslo_log import log
|
||||||
from tempest.common import utils as tutils
|
from tempest.common import utils as tutils
|
||||||
from tempest.lib.common.utils import data_utils
|
from tempest.lib.common.utils import data_utils
|
||||||
from tempest.lib import exceptions as lib_exc
|
from tempest.lib import exceptions as lib_exc
|
||||||
@ -31,6 +34,8 @@ from neutron_tempest_plugin import exceptions
|
|||||||
|
|
||||||
CONF = config.CONF
|
CONF = config.CONF
|
||||||
|
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class BaseNetworkTest(test.BaseTestCase):
|
class BaseNetworkTest(test.BaseTestCase):
|
||||||
|
|
||||||
@ -673,6 +678,16 @@ class BaseNetworkTest(test.BaseTestCase):
|
|||||||
cls.qos_rules.append(qos_rule)
|
cls.qos_rules.append(qos_rule)
|
||||||
return qos_rule
|
return qos_rule
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create_qos_minimum_bandwidth_rule(cls, policy_id, min_kbps,
|
||||||
|
direction=const.EGRESS_DIRECTION):
|
||||||
|
"""Wrapper utility that creates and returns a QoS min bw rule."""
|
||||||
|
body = cls.admin_client.create_minimum_bandwidth_rule(
|
||||||
|
policy_id, direction, min_kbps)
|
||||||
|
qos_rule = body['minimum_bandwidth_rule']
|
||||||
|
cls.qos_rules.append(qos_rule)
|
||||||
|
return qos_rule
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def delete_router(cls, router, client=None):
|
def delete_router(cls, router, client=None):
|
||||||
client = client or cls.client
|
client = client or cls.client
|
||||||
@ -974,6 +989,32 @@ class BaseAdminNetworkTest(BaseNetworkTest):
|
|||||||
"net(%s) has no usable IP address in allocation pools" % net_id)
|
"net(%s) has no usable IP address in allocation pools" % net_id)
|
||||||
raise exceptions.InvalidConfiguration(message)
|
raise exceptions.InvalidConfiguration(message)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create_provider_network(cls, physnet_name, start_segmentation_id,
|
||||||
|
max_attempts=30):
|
||||||
|
segmentation_id = start_segmentation_id
|
||||||
|
for attempts in itertools.count():
|
||||||
|
try:
|
||||||
|
prov_network = cls.create_network(
|
||||||
|
name=data_utils.rand_name('test_net'),
|
||||||
|
shared=True,
|
||||||
|
provider_network_type='vlan',
|
||||||
|
provider_physical_network=physnet_name,
|
||||||
|
provider_segmentation_id=segmentation_id)
|
||||||
|
break
|
||||||
|
except lib_exc.Conflict:
|
||||||
|
if attempts > max_attempts:
|
||||||
|
LOG.exception("Failed to create provider network after "
|
||||||
|
"%d attempts", attempts)
|
||||||
|
raise lib_exc.TimeoutException
|
||||||
|
segmentation_id += 1
|
||||||
|
if segmentation_id > 4095:
|
||||||
|
raise lib_exc.TempestException(
|
||||||
|
"No free segmentation id was found for provider "
|
||||||
|
"network creation!")
|
||||||
|
time.sleep(CONF.network.build_interval)
|
||||||
|
return prov_network
|
||||||
|
|
||||||
|
|
||||||
def require_qos_rule_type(rule_type):
|
def require_qos_rule_type(rule_type):
|
||||||
def decorator(f):
|
def decorator(f):
|
||||||
|
@ -21,6 +21,10 @@ NeutronPluginOptions = [
|
|||||||
cfg.ListOpt('provider_vlans',
|
cfg.ListOpt('provider_vlans',
|
||||||
default=[],
|
default=[],
|
||||||
help='List of provider networks available in the deployment.'),
|
help='List of provider networks available in the deployment.'),
|
||||||
|
cfg.IntOpt('provider_net_base_segm_id',
|
||||||
|
default=3000,
|
||||||
|
help='Base segmentation ID to create provider networks. '
|
||||||
|
'This value will be increased in case of conflict.'),
|
||||||
cfg.BoolOpt('specify_floating_ip_address_available',
|
cfg.BoolOpt('specify_floating_ip_address_available',
|
||||||
default=True,
|
default=True,
|
||||||
help='Allow passing an IP Address of the floating ip when '
|
help='Allow passing an IP Address of the floating ip when '
|
||||||
|
Loading…
Reference in New Issue
Block a user