From eaaf978e25b43f49a1f78c34651d4acd65236eeb Mon Sep 17 00:00:00 2001 From: Kailun Qin Date: Thu, 20 Dec 2018 04:45:01 +0800 Subject: [PATCH] Add API test for network segment range extension Co-authored-by: Allain Legacy Partially-implements: blueprint network-segment-range-management Change-Id: I4758fcdd45ac1f84d872ff1f6e1da8a8d4671a80 --- .zuul.yaml | 2 + .../api/admin/test_network_segment_range.py | 247 ++++++++++++++++++ neutron_tempest_plugin/api/base.py | 26 ++ 3 files changed, 275 insertions(+) create mode 100644 neutron_tempest_plugin/api/admin/test_network_segment_range.py diff --git a/.zuul.yaml b/.zuul.yaml index 65e00b77..03766304 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -45,6 +45,7 @@ - net-mtu-writable - network-ip-availability - network_availability_zone + - network-segment-range - pagination - port-resource-request - port-mac-address-regenerate @@ -90,6 +91,7 @@ neutron-segments: true neutron-trunk: true neutron-uplink-status-propagation: true + neutron-network-segment-range: true devstack_local_conf: post-config: $NEUTRON_CONF: diff --git a/neutron_tempest_plugin/api/admin/test_network_segment_range.py b/neutron_tempest_plugin/api/admin/test_network_segment_range.py new file mode 100644 index 00000000..e747fed9 --- /dev/null +++ b/neutron_tempest_plugin/api/admin/test_network_segment_range.py @@ -0,0 +1,247 @@ +# Copyright (c) 2019, Intel Corporation. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from tempest.lib.common.utils import data_utils +from tempest.lib import decorators +from tempest.lib import exceptions as lib_exc + +from neutron_tempest_plugin.api import base + +TEST_SEGMENT_RANGE_MINIMUM_ID = 1100 +TEST_SEGMENT_RANGE_MAXIMUM_ID = 1105 + + +class NetworkSegmentRangeTestBase(base.BaseAdminNetworkTest): + + required_extensions = ['network-segment-range'] + + @classmethod + def skip_checks(cls): + super(NetworkSegmentRangeTestBase, cls).skip_checks() + + @classmethod + def resource_setup(cls): + super(NetworkSegmentRangeTestBase, cls).resource_setup() + network_type = "vxlan" + physical_network = "" + minimum = TEST_SEGMENT_RANGE_MINIMUM_ID + maximum = TEST_SEGMENT_RANGE_MAXIMUM_ID + cls._network_segment_range_data = { + 'network_type': network_type, 'physical_network': physical_network, + 'minimum': minimum, 'maximum': maximum} + + def _create_network_segment_range(self, name=None, + shared=False, project_id=None, + network_type=None, physical_network=None, + minimum=None, maximum=None): + name = name or data_utils.rand_name('test_network_segment_range') + + if shared: + project_id = "" + else: + test_project = data_utils.rand_name('test_project') + test_description = data_utils.rand_name('desc') + project_id = self.create_project( + name=test_project, + description=test_description)['id'] + + network_type = (network_type or + self._network_segment_range_data['network_type']) + physical_network = ( + physical_network or + self._network_segment_range_data['physical_network']) + minimum = minimum or self._network_segment_range_data['minimum'] + maximum = maximum or self._network_segment_range_data['maximum'] + + network_segment_range = self.create_network_segment_range( + name=name, shared=shared, project_id=project_id, + network_type=network_type, physical_network=physical_network, + minimum=minimum, maximum=maximum) + # _delete_network_segment_range will ensure that the network segment + # range is really removed + self.addCleanup(self._delete_network_segment_range, + network_segment_range['id']) + + return network_segment_range + + def _delete_network_segment_range(self, network_segment_range_id): + # Deletes a network segment range and verifies if it is deleted or not + self.admin_client.delete_network_segment_range( + network_segment_range_id) + # Asserting that the network segment range is not found in list after + # deletion + labels = self.admin_client.list_network_segment_ranges( + id=network_segment_range_id) + list_range_ids = [r['id'] for r in labels['network_segment_ranges']] + self.assertNotIn(network_segment_range_id, list_range_ids) + + +class NetworkSegmentRangeTestJson(NetworkSegmentRangeTestBase): + """Test Network Segment Range + + Tests the following operations in the Neutron API using the REST client for + Neutron: + + List, Show, Create, Update, Delete Network Segment Range + """ + + @decorators.idempotent_id('44a1ece1-d85d-4253-92f8-4efc318a6d8e') + def test_create_update_delete_network_segment_range(self): + # Creates a network segment range + network_segment_range = self._create_network_segment_range() + self.assertIsNotNone(network_segment_range['id']) + self.assertFalse(network_segment_range['default']) + self.assertFalse(network_segment_range['shared']) + self.assertEqual('vxlan', network_segment_range['network_type']) + self.assertEqual(TEST_SEGMENT_RANGE_MINIMUM_ID, + network_segment_range['minimum']) + self.assertEqual(TEST_SEGMENT_RANGE_MAXIMUM_ID, + network_segment_range['maximum']) + # Updates a network segment range + updated_minimum = TEST_SEGMENT_RANGE_MINIMUM_ID - 50 + updated_maximum = TEST_SEGMENT_RANGE_MAXIMUM_ID + 50 + body = self.admin_client.update_network_segment_range( + network_segment_range['id'], name='new-range-name', + minimum=updated_minimum, maximum=updated_maximum) + updated_network_segment_range = body['network_segment_range'] + self.assertEqual('new-range-name', + updated_network_segment_range['name']) + self.assertEqual(updated_minimum, + updated_network_segment_range['minimum']) + self.assertEqual(updated_maximum, + updated_network_segment_range['maximum']) + + @decorators.idempotent_id('5e118fef-a139-4886-8250-07e73d2cbe7a') + def test_update_network_segment_range_failed_with_existing_range_impacted( + self): + # Creates a network segment range + network_segment_range = self._create_network_segment_range() + project_id = network_segment_range['project_id'] + # Creates a network + name = data_utils.rand_name('test_network_for_' + project_id) + network = self.create_network( + name, client=self.admin_client, project_id=project_id) + # Updates a network segment range + updated_maximum = TEST_SEGMENT_RANGE_MAXIMUM_ID + 50 + self.assertRaises(lib_exc.Conflict, + self.admin_client.update_network_segment_range, + network_segment_range['id'], + name='new-range-name', + minimum=network['provider:segmentation_id'], + maximum=updated_maximum) + # network needs to be deleted otherwise the range deletion will fail + # because the segment is in use (assigned to the network created) + self.admin_client.delete_network(network['id']) + + @decorators.idempotent_id('0019de49-c0ea-4554-af57-18ad4ae30195') + def test_create_network_with_tenant_specific_network_segment_range(self): + # Creates a network segment range + network_segment_range = self._create_network_segment_range() + project_id = network_segment_range['project_id'] + # Creates a set of networks + network_ids = [] + for _ in range(TEST_SEGMENT_RANGE_MAXIMUM_ID - + TEST_SEGMENT_RANGE_MINIMUM_ID + 1): + name = data_utils.rand_name('test_network_for_' + project_id) + network = self.create_network( + name, client=self.admin_client, project_id=project_id) + + observed_network = self.admin_client.show_network( + network['id'])['network'] + network_ids.append(network['id']) + self.assertTrue( + TEST_SEGMENT_RANGE_MINIMUM_ID <= + observed_network['provider:segmentation_id'] <= + TEST_SEGMENT_RANGE_MAXIMUM_ID) + # networks need to be deleted otherwise the range deletion will fail + # because the segments are in use (assigned to the networks created) + for network_id in network_ids: + self.admin_client.delete_network(network_id) + + @decorators.idempotent_id('2129a26b-a97b-43d6-b0b2-04253c6046f8') + def test_create_network_with_default_network_segment_range(self): + # Creates a set of networks without creating a network segment range, + # i.e. using default network segment ranges only. + network_ids = [] + for _ in range(5): + name = data_utils.rand_name('test_network') + network = self.create_network(name) + + self.assertEqual(name, network['name']) + + observed_network = self.admin_client.show_network( + network['id'])['network'] + network_ids.append(network['id']) + self.assertEqual(name, observed_network['name']) + # default vxlan network segment range: 1-2000 + self.assertTrue( + 1 <= observed_network['provider:segmentation_id'] <= 2000) + # networks need to be deleted otherwise the range deletion will fail + # because the segments are in use (assigned to the networks created) + for network_id in network_ids: + self.admin_client.delete_network(network_id) + + @decorators.idempotent_id('54fa26c9-37b5-4df4-a934-a705f29920fc') + def test_show_network_segment_range(self): + # Creates a network segment range + network_segment_range = self._create_network_segment_range() + # Verifies the details of a network segment range + body = self.admin_client.show_network_segment_range( + network_segment_range['id']) + observed_range = body['network_segment_range'] + self.assertEqual(network_segment_range['id'], observed_range['id']) + self.assertEqual(network_segment_range['name'], observed_range['name']) + self.assertFalse(observed_range['default']) + self.assertFalse(observed_range['shared']) + self.assertEqual(network_segment_range['project_id'], + observed_range['project_id']) + self.assertEqual(network_segment_range['network_type'], + observed_range['network_type']) + self.assertEqual(network_segment_range['minimum'], + observed_range['minimum']) + self.assertEqual(network_segment_range['maximum'], + observed_range['maximum']) + + @decorators.idempotent_id('17139cc1-4826-4bf9-9c39-85b74894d938') + def test_list_network_segment_ranges(self): + # Creates a network segment range + network_segment_range = self._create_network_segment_range() + # Verify network segment range lists + body = self.admin_client.list_network_segment_ranges(id=33) + list_range_ids = [r['id'] for r in body['network_segment_ranges']] + self.assertNotIn(network_segment_range['id'], list_range_ids) + + body = self.admin_client.list_network_segment_ranges( + id=network_segment_range['id']) + list_range_ids = [r['id'] for r in body['network_segment_ranges']] + self.assertIn(network_segment_range['id'], list_range_ids) + + @decorators.idempotent_id('42959544-9956-4b0c-aec6-d56533323924') + def test_delete_network_segment_range_failed_with_segment_referenced( + self): + # Creates a network segment range + network_segment_range = self._create_network_segment_range() + project_id = network_segment_range['project_id'] + # Creates a network + name = data_utils.rand_name('test_network_for_' + project_id) + network = self.create_network( + name, client=self.admin_client, project_id=project_id) + # Deletes a network segment range + self.assertRaises(lib_exc.Conflict, + self.admin_client.delete_network_segment_range, + network_segment_range['id']) + # network needs to be deleted otherwise the range deletion will fail + # because the segment is in use (assigned to the network created) + self.admin_client.delete_network(network['id']) diff --git a/neutron_tempest_plugin/api/base.py b/neutron_tempest_plugin/api/base.py index 29431982..7b91d942 100644 --- a/neutron_tempest_plugin/api/base.py +++ b/neutron_tempest_plugin/api/base.py @@ -135,6 +135,7 @@ class BaseNetworkTest(test.BaseTestCase): cls.reserved_subnet_cidrs = set() cls.keypairs = [] cls.trunks = [] + cls.network_segment_ranges = [] @classmethod def resource_cleanup(cls): @@ -244,6 +245,12 @@ class BaseNetworkTest(test.BaseTestCase): for keypair in cls.keypairs: cls._try_delete_resource(cls.delete_keypair, keypair) + # Clean up network_segment_ranges + for network_segment_range in cls.network_segment_ranges: + cls._try_delete_resource( + cls.admin_client.delete_network_segment_range, + network_segment_range['id']) + super(BaseNetworkTest, cls).resource_cleanup() @classmethod @@ -912,6 +919,25 @@ class BaseAdminNetworkTest(BaseNetworkTest): cls.metering_label_rules.append(metering_label_rule) return metering_label_rule + @classmethod + def create_network_segment_range(cls, name, shared, + project_id, network_type, + physical_network, minimum, + maximum): + """Wrapper utility that returns a test network segment range.""" + network_segment_range_args = {'name': name, + 'shared': shared, + 'project_id': project_id, + 'network_type': network_type, + 'physical_network': physical_network, + 'minimum': minimum, + 'maximum': maximum} + body = cls.admin_client.create_network_segment_range( + **network_segment_range_args) + network_segment_range = body['network_segment_range'] + cls.network_segment_ranges.append(network_segment_range) + return network_segment_range + @classmethod def create_flavor(cls, name, description, service_type): """Wrapper utility that returns a test flavor."""