From 52cc4bfa0a174b45bee9d9b084cbbe809113fb59 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Sat, 21 Sep 2019 17:33:37 +0100 Subject: [PATCH] nova-net: Migrate 'test_floating_ips' functional tests This is probably the most involved of all the changes and requires a significant expansion of the NeutronFixture to mock floating IP interactions. All the API samples were based off responses pulled from a DevStack configuration using openstackclient and old versions of the novaclient (where the 'floating-ip-*' commands were still present) in debug mode. Change-Id: Ib2f10a51bebd10cc69b78427b485aeac19f59141 Signed-off-by: Stephen Finucane --- .../floating-ips-create-req.json | 4 +- .../floating-ips-create-resp.json | 8 +- .../floating-ips-get-resp.json | 8 +- .../floating-ips-list-empty-resp.json | 2 +- .../floating-ips-list-resp.json | 14 +- .../floating-ips-create-resp.json.tpl | 6 +- .../floating-ips-get-resp.json.tpl | 6 +- .../floating-ips-list-resp.json.tpl | 12 +- .../api_sample_tests/test_floating_ips.py | 186 ++++++++++++++---- nova/tests/functional/integrated_helpers.py | 7 +- 10 files changed, 186 insertions(+), 67 deletions(-) diff --git a/doc/api_samples/os-floating-ips/floating-ips-create-req.json b/doc/api_samples/os-floating-ips/floating-ips-create-req.json index 511b009bede9..4bba875a5c43 100644 --- a/doc/api_samples/os-floating-ips/floating-ips-create-req.json +++ b/doc/api_samples/os-floating-ips/floating-ips-create-req.json @@ -1,3 +1,3 @@ { - "pool": "nova" -} \ No newline at end of file + "pool": "public" +} diff --git a/doc/api_samples/os-floating-ips/floating-ips-create-resp.json b/doc/api_samples/os-floating-ips/floating-ips-create-resp.json index fe161a7dd129..33c2c350b861 100644 --- a/doc/api_samples/os-floating-ips/floating-ips-create-resp.json +++ b/doc/api_samples/os-floating-ips/floating-ips-create-resp.json @@ -1,9 +1,9 @@ { "floating_ip": { "fixed_ip": null, - "id": 1, + "id": "8baeddb4-45e2-4c36-8cb7-d79439a5f67c", "instance_id": null, - "ip": "10.10.10.1", - "pool": "nova" + "ip": "172.24.4.17", + "pool": "public" } -} \ No newline at end of file +} diff --git a/doc/api_samples/os-floating-ips/floating-ips-get-resp.json b/doc/api_samples/os-floating-ips/floating-ips-get-resp.json index fe161a7dd129..33c2c350b861 100644 --- a/doc/api_samples/os-floating-ips/floating-ips-get-resp.json +++ b/doc/api_samples/os-floating-ips/floating-ips-get-resp.json @@ -1,9 +1,9 @@ { "floating_ip": { "fixed_ip": null, - "id": 1, + "id": "8baeddb4-45e2-4c36-8cb7-d79439a5f67c", "instance_id": null, - "ip": "10.10.10.1", - "pool": "nova" + "ip": "172.24.4.17", + "pool": "public" } -} \ No newline at end of file +} diff --git a/doc/api_samples/os-floating-ips/floating-ips-list-empty-resp.json b/doc/api_samples/os-floating-ips/floating-ips-list-empty-resp.json index 121dbd084e87..12f118da50dd 100644 --- a/doc/api_samples/os-floating-ips/floating-ips-list-empty-resp.json +++ b/doc/api_samples/os-floating-ips/floating-ips-list-empty-resp.json @@ -1,3 +1,3 @@ { "floating_ips": [] -} \ No newline at end of file +} diff --git a/doc/api_samples/os-floating-ips/floating-ips-list-resp.json b/doc/api_samples/os-floating-ips/floating-ips-list-resp.json index 4d58e0676a93..8585c4c7f9d8 100644 --- a/doc/api_samples/os-floating-ips/floating-ips-list-resp.json +++ b/doc/api_samples/os-floating-ips/floating-ips-list-resp.json @@ -2,17 +2,17 @@ "floating_ips": [ { "fixed_ip": null, - "id": 1, + "id": "8baeddb4-45e2-4c36-8cb7-d79439a5f67c", "instance_id": null, - "ip": "10.10.10.1", - "pool": "nova" + "ip": "172.24.4.17", + "pool": "public" }, { "fixed_ip": null, - "id": 2, + "id": "05ef7490-745a-4af9-98e5-610dc97493c4", "instance_id": null, - "ip": "10.10.10.2", - "pool": "nova" + "ip": "172.24.4.78", + "pool": "public" } ] -} \ No newline at end of file +} diff --git a/nova/tests/functional/api_sample_tests/api_samples/os-floating-ips/floating-ips-create-resp.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/os-floating-ips/floating-ips-create-resp.json.tpl index 10ee8d9bd402..33c2c350b861 100644 --- a/nova/tests/functional/api_sample_tests/api_samples/os-floating-ips/floating-ips-create-resp.json.tpl +++ b/nova/tests/functional/api_sample_tests/api_samples/os-floating-ips/floating-ips-create-resp.json.tpl @@ -1,9 +1,9 @@ { "floating_ip": { "fixed_ip": null, - "id": 1, + "id": "8baeddb4-45e2-4c36-8cb7-d79439a5f67c", "instance_id": null, - "ip": "10.10.10.1", - "pool": "nova" + "ip": "172.24.4.17", + "pool": "public" } } diff --git a/nova/tests/functional/api_sample_tests/api_samples/os-floating-ips/floating-ips-get-resp.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/os-floating-ips/floating-ips-get-resp.json.tpl index 10ee8d9bd402..33c2c350b861 100644 --- a/nova/tests/functional/api_sample_tests/api_samples/os-floating-ips/floating-ips-get-resp.json.tpl +++ b/nova/tests/functional/api_sample_tests/api_samples/os-floating-ips/floating-ips-get-resp.json.tpl @@ -1,9 +1,9 @@ { "floating_ip": { "fixed_ip": null, - "id": 1, + "id": "8baeddb4-45e2-4c36-8cb7-d79439a5f67c", "instance_id": null, - "ip": "10.10.10.1", - "pool": "nova" + "ip": "172.24.4.17", + "pool": "public" } } diff --git a/nova/tests/functional/api_sample_tests/api_samples/os-floating-ips/floating-ips-list-resp.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/os-floating-ips/floating-ips-list-resp.json.tpl index 06f57451c9d8..6349ebea59ce 100644 --- a/nova/tests/functional/api_sample_tests/api_samples/os-floating-ips/floating-ips-list-resp.json.tpl +++ b/nova/tests/functional/api_sample_tests/api_samples/os-floating-ips/floating-ips-list-resp.json.tpl @@ -2,17 +2,17 @@ "floating_ips": [ { "fixed_ip": null, - "id": 1, + "id": "8baeddb4-45e2-4c36-8cb7-d79439a5f67c", "instance_id": null, - "ip": "10.10.10.1", - "pool": "nova" + "ip": "172.24.4.17", + "pool": "public" }, { "fixed_ip": null, - "id": 2, + "id": "05ef7490-745a-4af9-98e5-610dc97493c4", "instance_id": null, - "ip": "10.10.10.2", - "pool": "nova" + "ip": "172.24.4.78", + "pool": "public" } ] } diff --git a/nova/tests/functional/api_sample_tests/test_floating_ips.py b/nova/tests/functional/api_sample_tests/test_floating_ips.py index ebba1b9341bb..ec529de60945 100644 --- a/nova/tests/functional/api_sample_tests/test_floating_ips.py +++ b/nova/tests/functional/api_sample_tests/test_floating_ips.py @@ -12,47 +12,166 @@ # License for the specific language governing permissions and limitations # under the License. +import copy import nova.conf -from nova import context +from nova.tests import fixtures from nova.tests.functional.api_sample_tests import api_sample_base CONF = nova.conf.CONF +# TODO(stephenfin): Merge this back into the main class. We have to be careful +# with how we do this since if we register two networks we'll have ambiguous +# networks breaking auto-allocation +class NeutronFixture(fixtures.NeutronFixture): + + network_1 = { + 'id': fixtures.NeutronFixture.network_1['id'], + 'name': 'public', + 'description': '', + 'status': 'ACTIVE', + 'subnets': [ + # NOTE(stephenfin): We set this below + ], + 'admin_state_up': True, + 'tenant_id': fixtures.NeutronFixture.tenant_id, + 'project_id': fixtures.NeutronFixture.tenant_id, + 'shared': False, + 'mtu': 1500, + 'router:external': True, + 'availability_zone_hints': [], + 'availability_zones': [ + 'nova' + ], + 'port_security_enabled': True, + 'ipv4_address_scope': None, + 'ipv6_address_scope': None, + 'is_default': True, + } + + subnet_1 = { + 'id': '6b0b19d2-22b8-45f9-bf32-06d0b89f2d47', + 'name': 'public-subnet', + 'description': '', + 'ip_version': 4, + 'ipv6_address_mode': None, + 'ipv6_ra_mode': None, + 'enable_dhcp': False, + 'network_id': network_1['id'], + 'tenant_id': fixtures.NeutronFixture.tenant_id, + 'project_id': fixtures.NeutronFixture.tenant_id, + 'dns_nameservers': [], + 'gateway_ip': '172.24.4.1', + 'allocation_pools': [ + { + 'start': '172.24.4.2', + 'end': '172.24.4.254' + } + ], + 'host_routes': [], + 'cidr': '172.24.4.0/24', + } + subnet_2 = { + 'id': '503505c5-0dd2-4756-b355-4056aa0b6338', + 'name': 'ipv6-public-subnet', + 'description': '', + 'ip_version': 6, + 'ipv6_address_mode': None, + 'ipv6_ra_mode': None, + 'enable_dhcp': False, + 'network_id': network_1['id'], + 'tenant_id': fixtures.NeutronFixture.tenant_id, + 'project_id': fixtures.NeutronFixture.tenant_id, + 'dns_nameservers': [], + 'gateway_ip': '2001:db8::2', + 'allocation_pools': [ + {'start': '2001:db8::1', 'end': '2001:db8::1'}, + {'start': '2001:db8::3', 'end': '2001:db8::ffff:ffff:ffff:ffff'}, + ], + 'host_routes': [], + 'cidr': '2001:db8::/64', + } + network_1['subnets'] = [subnet_1['id'], subnet_2['id']] + + floatingip_1 = { + 'id': '8baeddb4-45e2-4c36-8cb7-d79439a5f67c', + 'description': '', + 'status': 'DOWN', + 'floating_ip_address': '172.24.4.17', + 'fixed_ip_address': None, + 'router_id': None, + 'tenant_id': fixtures.NeutronFixture.tenant_id, + 'project_id': fixtures.NeutronFixture.tenant_id, + 'floating_network_id': network_1['id'], + 'port_details': None, + 'port_id': None, + } + floatingip_2 = { + 'id': '05ef7490-745a-4af9-98e5-610dc97493c4', + 'description': '', + 'status': 'DOWN', + 'floating_ip_address': '172.24.4.78', + 'fixed_ip_address': None, + 'router_id': None, + 'tenant_id': fixtures.NeutronFixture.tenant_id, + 'project_id': fixtures.NeutronFixture.tenant_id, + 'floating_network_id': network_1['id'], + 'port_details': None, + 'port_id': None, + } + + def __init__(self, test): + super(NeutronFixture, self).__init__(test) + + self._ports = {} + self._networks = { + self.network_1['id']: copy.deepcopy(self.network_1), + } + self._floatingips = {} + self._subnets = { + self.subnet_1['id']: copy.deepcopy(self.subnet_1), + self.subnet_2['id']: copy.deepcopy(self.subnet_2), + } + + def create_floatingip(self, body=None): + for floatingip in [self.floatingip_1, self.floatingip_2]: + if floatingip['id'] not in self._floatingips: + self._floatingips[floatingip['id']] = copy.deepcopy(floatingip) + break + else: + # we can extend this later, if necessary + raise Exception('We only support adding a max of two floating IPs') + + return {'floatingip': floatingip} + + def delete_floatingip(self, floatingip): + if floatingip not in self._floatingips: + raise Exception('This floating IP has not been added yet') + + del self._floatingips[floatingip] + + def show_floatingip(self, floatingip, **_params): + if floatingip not in self._floatingips: + raise Exception('This floating IP has not been added yet') + + return {'floatingip': self._floatingips[floatingip]} + + def list_floatingips(self, retrieve_all=True, **_params): + return {'floatingips': copy.deepcopy(list(self._floatingips.values()))} + + class FloatingIpsTest(api_sample_base.ApiSampleTestBaseV21): - USE_NEUTRON = False sample_dir = "os-floating-ips" def setUp(self): super(FloatingIpsTest, self).setUp() - pool = CONF.default_floating_pool - interface = CONF.public_interface - self.ip_pool = [ - { - 'address': "10.10.10.1", - 'pool': pool, - 'interface': interface - }, - { - 'address': "10.10.10.2", - 'pool': pool, - 'interface': interface - }, - { - 'address': "10.10.10.3", - 'pool': pool, - 'interface': interface - }, - ] - self.compute.db.floating_ip_bulk_create( - context.get_admin_context(), self.ip_pool) + # we use a custom NeutronFixture that mocks out floating IP stuff + self.neutron = self.useFixture(NeutronFixture(self)) - def tearDown(self): - self.compute.db.floating_ip_bulk_destroy( - context.get_admin_context(), self.ip_pool) - super(FloatingIpsTest, self).tearDown() + # we also use a more useful default floating pool value + self.flags(default_floating_pool='public', group='neutron') def test_floating_ips_list_empty(self): response = self._do_get('os-floating-ips') @@ -76,18 +195,17 @@ class FloatingIpsTest(api_sample_base.ApiSampleTestBaseV21): def test_floating_ips_create(self): response = self._do_post('os-floating-ips', 'floating-ips-create-req', - {"pool": CONF.default_floating_pool}) + {'pool': 'public'}) self._verify_response('floating-ips-create-resp', {}, response, 200) + return response def test_floating_ips_get(self): - self.test_floating_ips_create() - # NOTE(sdague): the first floating ip will always have 1 as an id, - # but it would be better if we could get this from the create - response = self._do_get('os-floating-ips/%d' % 1) + floatingip = self.test_floating_ips_create().json()['floating_ip'] + response = self._do_get('os-floating-ips/%s' % floatingip['id']) self._verify_response('floating-ips-get-resp', {}, response, 200) def test_floating_ips_delete(self): - self.test_floating_ips_create() - response = self._do_delete('os-floating-ips/%d' % 1) + floatingip = self.test_floating_ips_create().json()['floating_ip'] + response = self._do_delete('os-floating-ips/%s' % floatingip['id']) self.assertEqual(202, response.status_code) self.assertEqual("", response.text) diff --git a/nova/tests/functional/integrated_helpers.py b/nova/tests/functional/integrated_helpers.py index ee9c31bdd41a..dfa4c8791afd 100644 --- a/nova/tests/functional/integrated_helpers.py +++ b/nova/tests/functional/integrated_helpers.py @@ -98,6 +98,9 @@ class _IntegratedTestBase(test.TestCase): placement = self.useFixture(func_fixtures.PlacementFixture()) self.placement_api = placement.api + if self.USE_NEUTRON: + self.neutron = self.useFixture(nova_fixtures.NeutronFixture(self)) + self._setup_services() self.addCleanup(nova.tests.unit.image.fake.FakeImageService_reset) @@ -116,9 +119,7 @@ class _IntegratedTestBase(test.TestCase): self.flags(transport_url=self.cell_mappings['cell1'].transport_url) self.conductor = self.start_service('conductor') - if self.USE_NEUTRON: - self.neutron = self.useFixture(nova_fixtures.NeutronFixture(self)) - else: + if not self.USE_NEUTRON: self.network = self.start_service('network', manager=CONF.network_manager) self.scheduler = self._setup_scheduler_service()