Merge "Remove unused LOG"
diff --git a/neutron/tests/tempest/api/base.py b/neutron/tests/tempest/api/base.py
index 2d836d6..84d91df 100644
--- a/neutron/tests/tempest/api/base.py
+++ b/neutron/tests/tempest/api/base.py
@@ -491,6 +491,8 @@
# This should be defined by subclasses to reflect resource name to test
resource = None
+ field = 'name'
+
# NOTE(ihrachys): some names, like those starting with an underscore (_)
# are sorted differently depending on whether the plugin implements native
# sorting support, or not. So we avoid any such cases here, sticking to
@@ -510,7 +512,7 @@
actual = list(actual)
self.assertEqual(len(original), len(actual))
for expected, res in zip(original, actual):
- self.assertEqual(expected['name'], res['name'])
+ self.assertEqual(expected[self.field], res[self.field])
@utils.classproperty
def plural_name(self):
@@ -537,13 +539,13 @@
def _test_list_sorts(self, direction):
sort_args = {
'sort_dir': direction,
- 'sort_key': 'name'
+ 'sort_key': self.field
}
body = self.list_method(**sort_args)
resources = self._extract_resources(body)
self.assertNotEmpty(
resources, "%s list returned is empty" % self.resource)
- retrieved_names = [res['name'] for res in resources]
+ retrieved_names = [res[self.field] for res in resources]
expected = sorted(retrieved_names)
if direction == constants.SORT_DIRECTION_DESC:
expected = list(reversed(expected))
@@ -580,7 +582,7 @@
# first, collect all resources for later comparison
sort_args = {
'sort_dir': constants.SORT_DIRECTION_ASC,
- 'sort_key': 'name'
+ 'sort_key': self.field
}
body = self.list_method(**sort_args)
expected_resources = self._extract_resources(body)
@@ -666,7 +668,7 @@
self, direction=constants.SORT_DIRECTION_ASC):
pagination_args = {
'sort_dir': direction,
- 'sort_key': 'name',
+ 'sort_key': self.field,
}
body = self.list_method(**pagination_args)
expected_resources = self._extract_resources(body)
@@ -709,7 +711,7 @@
def _test_list_pagination_page_reverse(self, direction):
pagination_args = {
'sort_dir': direction,
- 'sort_key': 'name',
+ 'sort_key': self.field,
'limit': 3,
}
body = self.list_method(**pagination_args)
diff --git a/neutron/tests/tempest/api/clients.py b/neutron/tests/tempest/api/clients.py
index 8b51c6e..c6f41d0 100644
--- a/neutron/tests/tempest/api/clients.py
+++ b/neutron/tests/tempest/api/clients.py
@@ -15,8 +15,8 @@
from tempest.lib.services.compute import keypairs_client
from tempest.lib.services.compute import servers_client
+from tempest.lib.services.identity.v2 import tenants_client
from tempest import manager
-from tempest.services.identity.v2.json import tenants_client
from neutron.tests.tempest import config
from neutron.tests.tempest.services.network.json import network_client
diff --git a/neutron/tests/tempest/api/test_network_ip_availability.py b/neutron/tests/tempest/api/test_network_ip_availability.py
index 74395ea..6a81128 100644
--- a/neutron/tests/tempest/api/test_network_ip_availability.py
+++ b/neutron/tests/tempest/api/test_network_ip_availability.py
@@ -86,7 +86,7 @@
mask_bits = config.safe_get_config_value(
'network', 'project_network_v6_mask_bits')
- subnet_cidr = cidr.subnet(mask_bits).next()
+ subnet_cidr = next(cidr.subnet(mask_bits))
prefix_len = subnet_cidr.prefixlen
subnet = self.create_subnet(network,
cidr=subnet_cidr,
diff --git a/neutron/tests/tempest/api/test_trunk.py b/neutron/tests/tempest/api/test_trunk.py
new file mode 100644
index 0000000..640584a
--- /dev/null
+++ b/neutron/tests/tempest/api/test_trunk.py
@@ -0,0 +1,183 @@
+# Copyright 2016 Hewlett Packard Enterprise Development Company LP
+#
+# 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 import exceptions as lib_exc
+from tempest import test
+
+from neutron.tests.tempest.api import base
+
+
+class TrunkTestJSONBase(base.BaseAdminNetworkTest):
+
+ def _create_trunk_with_network_and_parent(self, subports):
+ network = self.create_network()
+ parent_port = self.create_port(network)
+ return self.client.create_trunk(parent_port['id'], subports)
+
+
+class TrunkTestJSON(TrunkTestJSONBase):
+
+ @classmethod
+ @test.requires_ext(extension="trunk", service="network")
+ def resource_setup(cls):
+ super(TrunkTestJSON, cls).resource_setup()
+
+ def tearDown(self):
+ # NOTE(tidwellr) These tests create networks and ports, clean them up
+ # after each test to avoid hitting quota limits
+ self.resource_cleanup()
+ super(TrunkTestJSON, self).tearDown()
+
+ @test.idempotent_id('e1a6355c-4768-41f3-9bf8-0f1d192bd501')
+ def test_create_trunk_empty_subports_list(self):
+ trunk = self._create_trunk_with_network_and_parent([])
+ observed_trunk = self.client.show_trunk(trunk['trunk']['id'])
+ self.assertEqual(trunk, observed_trunk)
+
+ @test.idempotent_id('382dfa39-ca03-4bd3-9a1c-91e36d2e3796')
+ def test_create_trunk_subports_not_specified(self):
+ trunk = self._create_trunk_with_network_and_parent(None)
+ observed_trunk = self.client.show_trunk(trunk['trunk']['id'])
+ self.assertEqual(trunk, observed_trunk)
+
+ @test.idempotent_id('7de46c22-e2b6-4959-ac5a-0e624632ab32')
+ def test_create_show_delete_trunk(self):
+ trunk = self._create_trunk_with_network_and_parent(None)
+ trunk_id = trunk['trunk']['id']
+ parent_port_id = trunk['trunk']['port_id']
+ res = self.client.show_trunk(trunk_id)
+ self.assertEqual(trunk_id, res['trunk']['id'])
+ self.assertEqual(parent_port_id, res['trunk']['port_id'])
+ self.client.delete_trunk(trunk_id)
+ self.assertRaises(lib_exc.NotFound, self.client.show_trunk, trunk_id)
+
+ @test.idempotent_id('73365f73-bed6-42cd-960b-ec04e0c99d85')
+ def test_list_trunks(self):
+ trunk1 = self._create_trunk_with_network_and_parent(None)
+ trunk2 = self._create_trunk_with_network_and_parent(None)
+ expected_trunks = {trunk1['trunk']['id']: trunk1['trunk'],
+ trunk2['trunk']['id']: trunk2['trunk']}
+ trunk_list = self.client.list_trunks()['trunks']
+ matched_trunks = [x for x in trunk_list if x['id'] in expected_trunks]
+ self.assertEqual(2, len(matched_trunks))
+ for trunk in matched_trunks:
+ self.assertEqual(expected_trunks[trunk['id']], trunk)
+
+ @test.idempotent_id('bb5fcead-09b5-484a-bbe6-46d1e06d6cc0')
+ def test_add_subport(self):
+ trunk = self._create_trunk_with_network_and_parent([])
+ network = self.create_network()
+ port = self.create_port(network)
+ subports = [{'port_id': port['id'],
+ 'segmentation_type': 'vlan',
+ 'segmentation_id': 2}]
+ self.client.add_subports(trunk['trunk']['id'], subports)
+ trunk = self.client.show_trunk(trunk['trunk']['id'])
+ observed_subports = trunk['trunk']['sub_ports']
+ self.assertEqual(1, len(observed_subports))
+ created_subport = observed_subports[0]
+ self.assertEqual(subports[0], created_subport)
+
+ @test.idempotent_id('96eea398-a03c-4c3e-a99e-864392c2ca53')
+ def test_remove_subport(self):
+ subport_parent1 = self.create_port(self.create_network())
+ subport_parent2 = self.create_port(self.create_network())
+ subports = [{'port_id': subport_parent1['id'],
+ 'segmentation_type': 'vlan',
+ 'segmentation_id': 2},
+ {'port_id': subport_parent2['id'],
+ 'segmentation_type': 'vlan',
+ 'segmentation_id': 4}]
+ trunk = self._create_trunk_with_network_and_parent(subports)
+ removed_subport = trunk['trunk']['sub_ports'][0]
+ expected_subport = None
+
+ for subport in subports:
+ if subport['port_id'] != removed_subport['port_id']:
+ expected_subport = subport
+ break
+
+ # Remove the subport and validate PUT response
+ res = self.client.remove_subports(trunk['trunk']['id'],
+ [removed_subport])
+ self.assertEqual(1, len(res['sub_ports']))
+ self.assertEqual(expected_subport, res['sub_ports'][0])
+
+ # Validate the results of a subport list
+ trunk = self.client.show_trunk(trunk['trunk']['id'])
+ observed_subports = trunk['trunk']['sub_ports']
+ self.assertEqual(1, len(observed_subports))
+ self.assertEqual(expected_subport, observed_subports[0])
+
+ @test.idempotent_id('bb5fcaad-09b5-484a-dde6-4cd1ea6d6ff0')
+ def test_get_subports(self):
+ network = self.create_network()
+ port = self.create_port(network)
+ subports = [{'port_id': port['id'],
+ 'segmentation_type': 'vlan',
+ 'segmentation_id': 2}]
+ trunk = self._create_trunk_with_network_and_parent(subports)
+ trunk = self.client.get_subports(trunk['trunk']['id'])
+ observed_subports = trunk['sub_ports']
+ self.assertEqual(1, len(observed_subports))
+
+
+class TrunksSearchCriteriaTest(base.BaseSearchCriteriaTest):
+
+ resource = 'trunk'
+ field = 'id'
+
+ @classmethod
+ def resource_setup(cls):
+ super(TrunksSearchCriteriaTest, cls).resource_setup()
+ net = cls.create_network(network_name='trunk-search-test-net')
+ for name in cls.resource_names:
+ parent_port = cls.create_port(net)
+ cls.client.create_trunk(parent_port['id'], [])
+
+ @test.idempotent_id('fab73df4-960a-4ae3-87d3-60992b8d3e2d')
+ def test_list_sorts_asc(self):
+ self._test_list_sorts_asc()
+
+ @test.idempotent_id('a426671d-7270-430f-82ff-8f33eec93010')
+ def test_list_sorts_desc(self):
+ self._test_list_sorts_desc()
+
+ @test.idempotent_id('b202fdc8-6616-45df-b6a0-463932de6f94')
+ def test_list_pagination(self):
+ self._test_list_pagination()
+
+ @test.idempotent_id('c4723b8e-8186-4b9a-bf9e-57519967e048')
+ def test_list_pagination_with_marker(self):
+ self._test_list_pagination_with_marker()
+
+ @test.idempotent_id('dcd02a7a-f07e-4d5e-b0ca-b58e48927a9b')
+ def test_list_pagination_with_href_links(self):
+ self._test_list_pagination_with_href_links()
+
+ @test.idempotent_id('eafe7024-77ab-4cfe-824b-0b2bf4217727')
+ def test_list_no_pagination_limit_0(self):
+ self._test_list_no_pagination_limit_0()
+
+ @test.idempotent_id('f8857391-dc44-40cc-89b7-2800402e03ce')
+ def test_list_pagination_page_reverse_asc(self):
+ self._test_list_pagination_page_reverse_asc()
+
+ @test.idempotent_id('ae51e9c9-ceae-4ec0-afd4-147569247699')
+ def test_list_pagination_page_reverse_desc(self):
+ self._test_list_pagination_page_reverse_desc()
+
+ @test.idempotent_id('b4293e59-d794-4a93-be09-38667199ef68')
+ def test_list_pagination_page_reverse_with_href_links(self):
+ self._test_list_pagination_page_reverse_with_href_links()
diff --git a/neutron/tests/tempest/api/test_trunk_negative.py b/neutron/tests/tempest/api/test_trunk_negative.py
new file mode 100644
index 0000000..1cf37b7
--- /dev/null
+++ b/neutron/tests/tempest/api/test_trunk_negative.py
@@ -0,0 +1,190 @@
+# Copyright 2016 Hewlett Packard Enterprise Development Company LP
+#
+# 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 oslo_utils import uuidutils
+from tempest.lib import exceptions as lib_exc
+from tempest import test
+
+from neutron.tests.tempest.api import test_trunk
+
+
+class TrunkTestJSON(test_trunk.TrunkTestJSONBase):
+
+ def tearDown(self):
+ # NOTE(tidwellr) These tests create networks and ports, clean them up
+ # after each test to avoid hitting quota limits
+ self.resource_cleanup()
+ super(TrunkTestJSON, self).tearDown()
+
+ @classmethod
+ @test.requires_ext(extension="trunk", service="network")
+ def resource_setup(cls):
+ super(test_trunk.TrunkTestJSONBase, cls).resource_setup()
+
+ @test.attr(type='negative')
+ @test.idempotent_id('1b5cf87a-1d3a-4a94-ba64-647153d54f32')
+ def test_create_trunk_nonexistent_port_id(self):
+ self.assertRaises(lib_exc.NotFound, self.client.create_trunk,
+ uuidutils.generate_uuid(), [])
+
+ @test.attr(type='negative')
+ @test.idempotent_id('980bca3b-b0be-45ac-8067-b401e445b796')
+ def test_create_trunk_nonexistent_subport_port_id(self):
+ network = self.create_network()
+ parent_port = self.create_port(network)
+ self.assertRaises(lib_exc.NotFound, self.client.create_trunk,
+ parent_port['id'],
+ [{'port_id': uuidutils.generate_uuid(),
+ 'segmentation_type': 'vlan',
+ 'segmentation_id': 2}])
+
+ @test.attr(type='negative')
+ @test.idempotent_id('a5c5200a-72a0-43c5-a11a-52f808490344')
+ def test_create_subport_nonexistent_port_id(self):
+ trunk = self._create_trunk_with_network_and_parent([])
+ self.assertRaises(lib_exc.NotFound, self.client.add_subports,
+ trunk['trunk']['id'],
+ [{'port_id': uuidutils.generate_uuid(),
+ 'segmentation_type': 'vlan',
+ 'segmentation_id': 2}])
+
+ @test.attr(type='negative')
+ @test.idempotent_id('80deb6a9-da2a-48db-b7fd-bcef5b14edc1')
+ def test_create_subport_nonexistent_trunk(self):
+ network = self.create_network()
+ parent_port = self.create_port(network)
+ self.assertRaises(lib_exc.NotFound, self.client.add_subports,
+ uuidutils.generate_uuid(),
+ [{'port_id': parent_port['id'],
+ 'segmentation_type': 'vlan',
+ 'segmentation_id': 2}])
+
+ @test.attr(type='negative')
+ @test.idempotent_id('7e0f99ab-fe37-408b-a889-9e44ef300084')
+ def test_create_subport_missing_segmentation_id(self):
+ trunk = self._create_trunk_with_network_and_parent([])
+ subport_network = self.create_network()
+ parent_port = self.create_port(subport_network)
+ self.assertRaises(lib_exc.BadRequest, self.client.add_subports,
+ trunk['trunk']['id'],
+ [{'port_id': parent_port['id'],
+ 'segmentation_type': 'vlan'}])
+
+ @test.attr(type='negative')
+ @test.idempotent_id('a315d78b-2f43-4efa-89ae-166044c568aa')
+ def test_create_trunk_with_subport_missing_segmentation_id(self):
+ subport_network = self.create_network()
+ parent_port = self.create_port(subport_network)
+ self.assertRaises(lib_exc.BadRequest, self.client.create_trunk,
+ parent_port['id'],
+ [{'port_id': uuidutils.generate_uuid(),
+ 'segmentation_type': 'vlan'}])
+
+ @test.attr(type='negative')
+ @test.idempotent_id('33498618-f75a-4796-8ae6-93d4fd203fa4')
+ def test_create_trunk_with_subport_missing_segmentation_type(self):
+ subport_network = self.create_network()
+ parent_port = self.create_port(subport_network)
+ self.assertRaises(lib_exc.BadRequest, self.client.create_trunk,
+ parent_port['id'],
+ [{'port_id': uuidutils.generate_uuid(),
+ 'segmentation_id': 3}])
+
+ @test.attr(type='negative')
+ @test.idempotent_id('a717691c-4e07-4d81-a98d-6f1c18c5d183')
+ def test_create_trunk_with_subport_missing_port_id(self):
+ subport_network = self.create_network()
+ parent_port = self.create_port(subport_network)
+ self.assertRaises(lib_exc.BadRequest, self.client.create_trunk,
+ parent_port['id'],
+ [{'segmentation_type': 'vlan',
+ 'segmentation_id': 3}])
+
+ @test.attr(type='negative')
+ @test.idempotent_id('40aed9be-e976-47d0-a555-bde2c7e74e57')
+ def test_create_trunk_duplicate_subport_segmentation_ids(self):
+ trunk = self._create_trunk_with_network_and_parent([])
+ subport_network1 = self.create_network()
+ subport_network2 = self.create_network()
+ parent_port1 = self.create_port(subport_network1)
+ parent_port2 = self.create_port(subport_network2)
+ self.assertRaises(lib_exc.BadRequest, self.client.create_trunk,
+ trunk['trunk']['id'],
+ [{'port_id': parent_port1['id'],
+ 'segmentation_id': 2,
+ 'segmentation_type': 'vlan'},
+ {'port_id': parent_port2['id'],
+ 'segmentation_id': 2,
+ 'segmentation_type': 'vlan'}])
+
+ @test.attr(type='negative')
+ @test.idempotent_id('6f132ccc-1380-42d8-9c44-50411612bd01')
+ def test_add_subport_port_id_uses_trunk_port_id(self):
+ trunk = self._create_trunk_with_network_and_parent(None)
+ self.assertRaises(lib_exc.Conflict, self.client.add_subports,
+ trunk['trunk']['id'],
+ [{'port_id': trunk['trunk']['port_id'],
+ 'segmentation_type': 'vlan',
+ 'segmentation_id': 2}])
+
+ @test.attr(type='negative')
+ @test.idempotent_id('00cb40bb-1593-44c8-808c-72b47e64252f')
+ def test_add_subport_duplicate_segmentation_details(self):
+ trunk = self._create_trunk_with_network_and_parent(None)
+ network = self.create_network()
+ parent_port1 = self.create_port(network)
+ parent_port2 = self.create_port(network)
+ self.client.add_subports(trunk['trunk']['id'],
+ [{'port_id': parent_port1['id'],
+ 'segmentation_type': 'vlan',
+ 'segmentation_id': 2}])
+ self.assertRaises(lib_exc.Conflict, self.client.add_subports,
+ trunk['trunk']['id'],
+ [{'port_id': parent_port2['id'],
+ 'segmentation_type': 'vlan',
+ 'segmentation_id': 2}])
+
+ @test.attr(type='negative')
+ @test.idempotent_id('4eac8c25-83ee-4051-9620-34774f565730')
+ def test_add_subport_passing_dict(self):
+ trunk = self._create_trunk_with_network_and_parent(None)
+ self.assertRaises(lib_exc.BadRequest, self.client.add_subports,
+ trunk['trunk']['id'],
+ {'port_id': trunk['trunk']['port_id'],
+ 'segmentation_type': 'vlan',
+ 'segmentation_id': 2})
+
+ @test.attr(type='negative')
+ @test.idempotent_id('17ca7dd7-96a8-445a-941e-53c0c86c2fe2')
+ def test_remove_subport_passing_dict(self):
+ network = self.create_network()
+ parent_port = self.create_port(network)
+ subport_data = {'port_id': parent_port['id'],
+ 'segmentation_type': 'vlan',
+ 'segmentation_id': 2}
+ trunk = self._create_trunk_with_network_and_parent([subport_data])
+ self.assertRaises(lib_exc.BadRequest, self.client.remove_subports,
+ trunk['trunk']['id'], subport_data)
+
+ @test.attr(type='negative')
+ @test.idempotent_id('aaca7dd7-96b8-445a-931e-63f0d86d2fe2')
+ def test_remove_subport_not_found(self):
+ network = self.create_network()
+ parent_port = self.create_port(network)
+ subport_data = {'port_id': parent_port['id'],
+ 'segmentation_type': 'vlan',
+ 'segmentation_id': 2}
+ trunk = self._create_trunk_with_network_and_parent([])
+ self.assertRaises(lib_exc.NotFound, self.client.remove_subports,
+ trunk['trunk']['id'], [subport_data])
diff --git a/neutron/tests/tempest/services/network/json/network_client.py b/neutron/tests/tempest/services/network/json/network_client.py
index d9e333c..3220604 100644
--- a/neutron/tests/tempest/services/network/json/network_client.py
+++ b/neutron/tests/tempest/services/network/json/network_client.py
@@ -659,6 +659,64 @@
body = jsonutils.loads(body)
return service_client.ResponseBody(resp, body)
+ def create_trunk(self, parent_port_id, subports, tenant_id=None):
+ uri = '%s/trunks' % self.uri_prefix
+ post_data = {
+ 'trunk': {
+ 'port_id': parent_port_id,
+ }
+ }
+ if subports is not None:
+ post_data['trunk']['sub_ports'] = subports
+ if tenant_id is not None:
+ post_data['trunk']['tenant_id'] = tenant_id
+ resp, body = self.post(uri, self.serialize(post_data))
+ body = self.deserialize_single(body)
+ self.expected_success(201, resp.status)
+ return service_client.ResponseBody(resp, body)
+
+ def show_trunk(self, trunk_id):
+ uri = '%s/trunks/%s' % (self.uri_prefix, trunk_id)
+ resp, body = self.get(uri)
+ body = self.deserialize_single(body)
+ self.expected_success(200, resp.status)
+ return service_client.ResponseBody(resp, body)
+
+ def list_trunks(self, **kwargs):
+ uri = '%s/trunks' % self.uri_prefix
+ if kwargs:
+ uri += '?' + urlparse.urlencode(kwargs, doseq=1)
+ resp, body = self.get(uri)
+ self.expected_success(200, resp.status)
+ body = self.deserialize_single(body)
+ return service_client.ResponseBody(resp, body)
+
+ def delete_trunk(self, trunk_id):
+ uri = '%s/trunks/%s' % (self.uri_prefix, trunk_id)
+ resp, body = self.delete(uri)
+ self.expected_success(204, resp.status)
+ return service_client.ResponseBody(resp, body)
+
+ def _subports_action(self, action, trunk_id, subports):
+ uri = '%s/trunks/%s/%s' % (self.uri_prefix, trunk_id, action)
+ resp, body = self.put(uri, jsonutils.dumps(subports))
+ body = self.deserialize_single(body)
+ self.expected_success(200, resp.status)
+ return service_client.ResponseBody(resp, body)
+
+ def add_subports(self, trunk_id, subports):
+ return self._subports_action('add_subports', trunk_id, subports)
+
+ def remove_subports(self, trunk_id, subports):
+ return self._subports_action('remove_subports', trunk_id, subports)
+
+ def get_subports(self, trunk_id):
+ uri = '%s/trunks/%s/%s' % (self.uri_prefix, trunk_id, 'get_subports')
+ resp, body = self.get(uri)
+ self.expected_success(200, resp.status)
+ body = jsonutils.loads(body)
+ return service_client.ResponseBody(resp, body)
+
def get_auto_allocated_topology(self, tenant_id=None):
uri = '%s/auto-allocated-topology/%s' % (self.uri_prefix, tenant_id)
resp, body = self.get(uri)