diff --git a/doc/api_samples/all_extensions/extensions-get-resp.json b/doc/api_samples/all_extensions/extensions-get-resp.json index df8ed83e53d3..d7c2a646c780 100644 --- a/doc/api_samples/all_extensions/extensions-get-resp.json +++ b/doc/api_samples/all_extensions/extensions-get-resp.json @@ -232,6 +232,14 @@ "namespace": "http://docs.openstack.org/compute/ext/evacuate/api/v2", "updated": "2013-01-06T00:00:00+00:00" }, + { + "alias": "os-extended-floating-ips", + "description": "Adds optional fixed_address to the add floating IP command.", + "links": [], + "name": "ExtendedFloatingIps", + "namespace": "http://docs.openstack.org/compute/ext/extended_floating_ips/api/v2", + "updated": "2013-04-19T00:00:00+00:00" + }, { "alias": "os-fixed-ips", "description": "Fixed IPs support.", diff --git a/doc/api_samples/all_extensions/extensions-get-resp.xml b/doc/api_samples/all_extensions/extensions-get-resp.xml index 1ec2010dc3ac..f6213a3a92eb 100644 --- a/doc/api_samples/all_extensions/extensions-get-resp.xml +++ b/doc/api_samples/all_extensions/extensions-get-resp.xml @@ -103,6 +103,9 @@ Enables server evacuation. + + Adds optional fixed_address to the add floating IP command. + Fixed IPs support. diff --git a/doc/api_samples/os-extended-floating-ips/floating-ips-create-nopool-req.json b/doc/api_samples/os-extended-floating-ips/floating-ips-create-nopool-req.json new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/doc/api_samples/os-extended-floating-ips/floating-ips-create-nopool-req.xml b/doc/api_samples/os-extended-floating-ips/floating-ips-create-nopool-req.xml new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/doc/api_samples/os-extended-floating-ips/floating-ips-create-req.json b/doc/api_samples/os-extended-floating-ips/floating-ips-create-req.json new file mode 100644 index 000000000000..511b009bede9 --- /dev/null +++ b/doc/api_samples/os-extended-floating-ips/floating-ips-create-req.json @@ -0,0 +1,3 @@ +{ + "pool": "nova" +} \ No newline at end of file diff --git a/doc/api_samples/os-extended-floating-ips/floating-ips-create-req.xml b/doc/api_samples/os-extended-floating-ips/floating-ips-create-req.xml new file mode 100644 index 000000000000..f77525e74983 --- /dev/null +++ b/doc/api_samples/os-extended-floating-ips/floating-ips-create-req.xml @@ -0,0 +1,2 @@ + +nova \ No newline at end of file diff --git a/doc/api_samples/os-extended-floating-ips/floating-ips-create-resp.json b/doc/api_samples/os-extended-floating-ips/floating-ips-create-resp.json new file mode 100644 index 000000000000..fe161a7dd129 --- /dev/null +++ b/doc/api_samples/os-extended-floating-ips/floating-ips-create-resp.json @@ -0,0 +1,9 @@ +{ + "floating_ip": { + "fixed_ip": null, + "id": 1, + "instance_id": null, + "ip": "10.10.10.1", + "pool": "nova" + } +} \ No newline at end of file diff --git a/doc/api_samples/os-extended-floating-ips/floating-ips-create-resp.xml b/doc/api_samples/os-extended-floating-ips/floating-ips-create-resp.xml new file mode 100644 index 000000000000..e0f68ef503a6 --- /dev/null +++ b/doc/api_samples/os-extended-floating-ips/floating-ips-create-resp.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/doc/api_samples/os-extended-floating-ips/floating-ips-list-empty-resp.json b/doc/api_samples/os-extended-floating-ips/floating-ips-list-empty-resp.json new file mode 100644 index 000000000000..121dbd084e87 --- /dev/null +++ b/doc/api_samples/os-extended-floating-ips/floating-ips-list-empty-resp.json @@ -0,0 +1,3 @@ +{ + "floating_ips": [] +} \ No newline at end of file diff --git a/doc/api_samples/os-extended-floating-ips/floating-ips-list-empty-resp.xml b/doc/api_samples/os-extended-floating-ips/floating-ips-list-empty-resp.xml new file mode 100644 index 000000000000..da6f0d4ce993 --- /dev/null +++ b/doc/api_samples/os-extended-floating-ips/floating-ips-list-empty-resp.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/doc/api_samples/os-extended-floating-ips/floating-ips-list-resp.json b/doc/api_samples/os-extended-floating-ips/floating-ips-list-resp.json new file mode 100644 index 000000000000..4d58e0676a93 --- /dev/null +++ b/doc/api_samples/os-extended-floating-ips/floating-ips-list-resp.json @@ -0,0 +1,18 @@ +{ + "floating_ips": [ + { + "fixed_ip": null, + "id": 1, + "instance_id": null, + "ip": "10.10.10.1", + "pool": "nova" + }, + { + "fixed_ip": null, + "id": 2, + "instance_id": null, + "ip": "10.10.10.2", + "pool": "nova" + } + ] +} \ No newline at end of file diff --git a/doc/api_samples/os-extended-floating-ips/floating-ips-list-resp.xml b/doc/api_samples/os-extended-floating-ips/floating-ips-list-resp.xml new file mode 100644 index 000000000000..78348be553d1 --- /dev/null +++ b/doc/api_samples/os-extended-floating-ips/floating-ips-list-resp.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/nova/api/openstack/compute/contrib/extended_floating_ips.py b/nova/api/openstack/compute/contrib/extended_floating_ips.py new file mode 100644 index 000000000000..06f1fa903412 --- /dev/null +++ b/nova/api/openstack/compute/contrib/extended_floating_ips.py @@ -0,0 +1,27 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2012 OpenStack Foundation +# +# 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 nova.api.openstack import extensions + + +class Extended_floating_ips(extensions.ExtensionDescriptor): + """Adds optional fixed_address to the add floating IP command.""" + + name = "ExtendedFloatingIps" + alias = "os-extended-floating-ips" + namespace = ("http://docs.openstack.org/compute/ext/" + "extended_floating_ips/api/v2") + updated = "2013-04-19T00:00:00+00:00" diff --git a/nova/api/openstack/compute/contrib/floating_ips.py b/nova/api/openstack/compute/contrib/floating_ips.py index bf1246ccba73..32cf1eecec58 100644 --- a/nova/api/openstack/compute/contrib/floating_ips.py +++ b/nova/api/openstack/compute/contrib/floating_ips.py @@ -198,10 +198,11 @@ class FloatingIPController(object): class FloatingIPActionController(wsgi.Controller): - def __init__(self, *args, **kwargs): + def __init__(self, ext_mgr=None, *args, **kwargs): super(FloatingIPActionController, self).__init__(*args, **kwargs) self.compute_api = compute.API() self.network_api = network.API() + self.ext_mgr = ext_mgr @wsgi.action('addFloatingIp') def _add_floating_ip(self, req, id, body): @@ -230,18 +231,27 @@ class FloatingIPActionController(wsgi.Controller): msg = _('No fixed ips associated to instance') raise webob.exc.HTTPBadRequest(explanation=msg) - # TODO(tr3buchet): this will associate the floating IP with the - # first fixed_ip an instance has. This should be - # changed to support specifying a particular fixed_ip if - # multiple exist. - if len(fixed_ips) > 1: - msg = _('multiple fixed_ips exist, using the first: %s') - LOG.warning(msg, fixed_ips[0]['address']) + fixed_address = None + if self.ext_mgr.is_loaded('os-extended-floating-ips'): + if 'fixed_address' in body['addFloatingIp']: + fixed_address = body['addFloatingIp']['fixed_address'] + for fixed in fixed_ips: + if fixed['address'] == fixed_address: + break + else: + msg = _('Specified fixed address not assigned to instance') + raise webob.exc.HTTPBadRequest(explanation=msg) + + if not fixed_address: + fixed_address = fixed_ips[0]['address'] + if len(fixed_ips) > 1: + msg = _('multiple fixed_ips exist, using the first: %s') + LOG.warning(msg, fixed_address) try: self.network_api.associate_floating_ip(context, instance, floating_address=address, - fixed_address=fixed_ips[0]['address']) + fixed_address=fixed_address) except exception.FloatingIpAssociated: msg = _('floating ip is already associated') raise webob.exc.HTTPBadRequest(explanation=msg) @@ -318,6 +328,6 @@ class Floating_ips(extensions.ExtensionDescriptor): return resources def get_controller_extensions(self): - controller = FloatingIPActionController() + controller = FloatingIPActionController(self.ext_mgr) extension = extensions.ControllerExtension(self, 'servers', controller) return [extension] diff --git a/nova/tests/api/openstack/compute/contrib/test_floating_ips.py b/nova/tests/api/openstack/compute/contrib/test_floating_ips.py index 00759a7ef613..2dc6f29568b4 100644 --- a/nova/tests/api/openstack/compute/contrib/test_floating_ips.py +++ b/nova/tests/api/openstack/compute/contrib/test_floating_ips.py @@ -20,6 +20,7 @@ from lxml import etree import webob from nova.api.openstack.compute.contrib import floating_ips +from nova.api.openstack import extensions from nova import compute from nova.compute import utils as compute_utils from nova import context @@ -154,8 +155,10 @@ class FloatingIpTest(test.TestCase): self.context = context.get_admin_context() self._create_floating_ips() + self.ext_mgr = extensions.ExtensionManager() + self.ext_mgr.extensions = {} self.controller = floating_ips.FloatingIPController() - self.manager = floating_ips.FloatingIPActionController() + self.manager = floating_ips.FloatingIPActionController(self.ext_mgr) def tearDown(self): self._delete_floating_ip() @@ -315,8 +318,10 @@ class FloatingIpTest(test.TestCase): self.controller.delete(req, 1) def test_floating_ip_associate(self): + fixed_address = '192.168.1.100' + def fake_associate_floating_ip(*args, **kwargs): - pass + self.assertEqual(fixed_address, kwargs['fixed_address']) self.stubs.Set(network.api.API, "associate_floating_ip", fake_associate_floating_ip) @@ -326,8 +331,26 @@ class FloatingIpTest(test.TestCase): rsp = self.manager._add_floating_ip(req, 'test_inst', body) self.assertTrue(rsp.status_int == 202) - def test_associate_not_allocated_floating_ip_to_instance(self): + def test_not_extended_floating_ip_associate_fixed(self): + # Check that fixed_address is ignored if os-extended-floating-ips + # is not loaded + fixed_address_requested = '192.168.1.101' + fixed_address_allocated = '192.168.1.100' + def fake_associate_floating_ip(*args, **kwargs): + self.assertEqual(fixed_address_allocated, + kwargs['fixed_address']) + + self.stubs.Set(network.api.API, "associate_floating_ip", + fake_associate_floating_ip) + body = dict(addFloatingIp=dict(address=self.floating_ip, + fixed_address=fixed_address_requested)) + + req = fakes.HTTPRequest.blank('/v2/fake/servers/test_inst/action') + rsp = self.manager._add_floating_ip(req, 'test_inst', body) + self.assertTrue(rsp.status_int == 202) + + def test_associate_not_allocated_floating_ip_to_instance(self): def fake_associate_floating_ip(self, context, instance, floating_address, fixed_address, affect_auto_assigned=False): @@ -510,6 +533,106 @@ class FloatingIpTest(test.TestCase): body) +class ExtendedFloatingIpTest(test.TestCase): + floating_ip = "10.10.10.10" + floating_ip_2 = "10.10.10.11" + + def _create_floating_ips(self, floating_ips=None): + """Create a floating ip object.""" + if floating_ips is None: + floating_ips = [self.floating_ip] + elif not isinstance(floating_ips, (list, tuple)): + floating_ips = [floating_ips] + + def make_ip_dict(ip): + """Shortcut for creating floating ip dict.""" + return + + dict_ = {'pool': 'nova', 'host': 'fake_host'} + return db.floating_ip_bulk_create( + self.context, [dict(address=ip, **dict_) for ip in floating_ips], + ) + + def _delete_floating_ip(self): + db.floating_ip_destroy(self.context, self.floating_ip) + + def setUp(self): + super(ExtendedFloatingIpTest, self).setUp() + self.stubs.Set(compute.api.API, "get", + compute_api_get) + self.stubs.Set(network.api.API, "get_floating_ip", + network_api_get_floating_ip) + self.stubs.Set(network.api.API, "get_floating_ip_by_address", + network_api_get_floating_ip_by_address) + self.stubs.Set(network.api.API, "get_floating_ips_by_project", + network_api_get_floating_ips_by_project) + self.stubs.Set(network.api.API, "release_floating_ip", + network_api_release) + self.stubs.Set(network.api.API, "disassociate_floating_ip", + network_api_disassociate) + self.stubs.Set(network.api.API, "get_instance_id_by_floating_address", + get_instance_by_floating_ip_addr) + self.stubs.Set(compute_utils, "get_nw_info_for_instance", + stub_nw_info(self.stubs)) + self.flags( + osapi_compute_extension=[ + 'nova.api.openstack.compute.contrib.select_extensions'], + osapi_compute_ext_list=['Floating_ips', 'Extended_floating_ips']) + + fake_network.stub_out_nw_api_get_instance_nw_info(self.stubs, + spectacular=True) + self.stubs.Set(db, 'instance_get', + fake_instance_get) + + self.context = context.get_admin_context() + self._create_floating_ips() + + self.ext_mgr = extensions.ExtensionManager() + self.ext_mgr.extensions = {} + self.ext_mgr.extensions['os-floating-ips'] = True + self.ext_mgr.extensions['os-extended-floating-ips'] = True + self.controller = floating_ips.FloatingIPController() + self.manager = floating_ips.FloatingIPActionController(self.ext_mgr) + + def tearDown(self): + self._delete_floating_ip() + super(ExtendedFloatingIpTest, self).tearDown() + + def test_extended_floating_ip_associate_fixed(self): + fixed_address = '192.168.1.101' + + def fake_associate_floating_ip(*args, **kwargs): + self.assertEqual(fixed_address, kwargs['fixed_address']) + + self.stubs.Set(network.api.API, "associate_floating_ip", + fake_associate_floating_ip) + body = dict(addFloatingIp=dict(address=self.floating_ip, + fixed_address=fixed_address)) + + req = fakes.HTTPRequest.blank('/v2/fake/servers/test_inst/action') + rsp = self.manager._add_floating_ip(req, 'test_inst', body) + self.assertTrue(rsp.status_int == 202) + + def test_extended_floating_ip_associate_fixed_not_allocated(self): + def fake_associate_floating_ip(*args, **kwargs): + pass + + self.stubs.Set(network.api.API, "associate_floating_ip", + fake_associate_floating_ip) + body = dict(addFloatingIp=dict(address=self.floating_ip, + fixed_address='11.11.11.11')) + + req = webob.Request.blank('/v2/fake/servers/test_inst/action') + req.method = "POST" + req.body = jsonutils.dumps(body) + req.headers["content-type"] = "application/json" + resp = req.get_response(fakes.wsgi_app(init_only=('servers',))) + res_dict = jsonutils.loads(resp.body) + self.assertEqual(resp.status_int, 400) + self.assertEqual(res_dict['badRequest']['message'], + "Specified fixed address not assigned to instance") + + class FloatingIpSerializerTest(test.TestCase): def test_default_serializer(self): serializer = floating_ips.FloatingIPTemplate() diff --git a/nova/tests/api/openstack/compute/test_extensions.py b/nova/tests/api/openstack/compute/test_extensions.py index 658d0c474dda..6e400a075cec 100644 --- a/nova/tests/api/openstack/compute/test_extensions.py +++ b/nova/tests/api/openstack/compute/test_extensions.py @@ -167,6 +167,7 @@ class ExtensionControllerTest(ExtensionTestCase): "DeferredDelete", "DiskConfig", "ExtendedAvailabilityZone", + "ExtendedFloatingIps", "ExtendedIps", "ExtendedIpsMac", "ExtendedVIFNet", diff --git a/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.json.tpl b/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.json.tpl index 1d3d2ea90047..d559b4890f22 100644 --- a/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.json.tpl +++ b/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.json.tpl @@ -232,6 +232,14 @@ "namespace": "http://docs.openstack.org/compute/ext/evacuate/api/v2", "updated": "%(timestamp)s" }, + { + "alias": "os-extended-floating-ips", + "description": "%(text)s", + "links": [], + "name": "ExtendedFloatingIps", + "namespace": "http://docs.openstack.org/compute/ext/extended_floating_ips/api/v2", + "updated": "%(timestamp)s" + }, { "alias": "os-fixed-ips", "description": "Fixed IPs support.", diff --git a/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.xml.tpl b/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.xml.tpl index 440996966e12..cc9ae4c02685 100644 --- a/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.xml.tpl +++ b/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.xml.tpl @@ -87,6 +87,9 @@ %(text)s + + %(text)s + Fixed IPs support. diff --git a/nova/tests/integrated/api_samples/os-extended-floating-ips/floating-ips-create-nopool-req.json.tpl b/nova/tests/integrated/api_samples/os-extended-floating-ips/floating-ips-create-nopool-req.json.tpl new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/nova/tests/integrated/api_samples/os-extended-floating-ips/floating-ips-create-nopool-req.xml.tpl b/nova/tests/integrated/api_samples/os-extended-floating-ips/floating-ips-create-nopool-req.xml.tpl new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/nova/tests/integrated/api_samples/os-extended-floating-ips/floating-ips-create-req.json.tpl b/nova/tests/integrated/api_samples/os-extended-floating-ips/floating-ips-create-req.json.tpl new file mode 100644 index 000000000000..24129f4958e0 --- /dev/null +++ b/nova/tests/integrated/api_samples/os-extended-floating-ips/floating-ips-create-req.json.tpl @@ -0,0 +1,3 @@ +{ + "pool": "%(pool)s" +} \ No newline at end of file diff --git a/nova/tests/integrated/api_samples/os-extended-floating-ips/floating-ips-create-req.xml.tpl b/nova/tests/integrated/api_samples/os-extended-floating-ips/floating-ips-create-req.xml.tpl new file mode 100644 index 000000000000..a80147389daa --- /dev/null +++ b/nova/tests/integrated/api_samples/os-extended-floating-ips/floating-ips-create-req.xml.tpl @@ -0,0 +1,2 @@ + +%(pool)s \ No newline at end of file diff --git a/nova/tests/integrated/api_samples/os-extended-floating-ips/floating-ips-create-resp.json.tpl b/nova/tests/integrated/api_samples/os-extended-floating-ips/floating-ips-create-resp.json.tpl new file mode 100644 index 000000000000..10ee8d9bd402 --- /dev/null +++ b/nova/tests/integrated/api_samples/os-extended-floating-ips/floating-ips-create-resp.json.tpl @@ -0,0 +1,9 @@ +{ + "floating_ip": { + "fixed_ip": null, + "id": 1, + "instance_id": null, + "ip": "10.10.10.1", + "pool": "nova" + } +} diff --git a/nova/tests/integrated/api_samples/os-extended-floating-ips/floating-ips-create-resp.xml.tpl b/nova/tests/integrated/api_samples/os-extended-floating-ips/floating-ips-create-resp.xml.tpl new file mode 100644 index 000000000000..e0f68ef503a6 --- /dev/null +++ b/nova/tests/integrated/api_samples/os-extended-floating-ips/floating-ips-create-resp.xml.tpl @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/nova/tests/integrated/api_samples/os-extended-floating-ips/floating-ips-get-resp.json.tpl b/nova/tests/integrated/api_samples/os-extended-floating-ips/floating-ips-get-resp.json.tpl new file mode 100644 index 000000000000..10ee8d9bd402 --- /dev/null +++ b/nova/tests/integrated/api_samples/os-extended-floating-ips/floating-ips-get-resp.json.tpl @@ -0,0 +1,9 @@ +{ + "floating_ip": { + "fixed_ip": null, + "id": 1, + "instance_id": null, + "ip": "10.10.10.1", + "pool": "nova" + } +} diff --git a/nova/tests/integrated/api_samples/os-extended-floating-ips/floating-ips-get-resp.xml.tpl b/nova/tests/integrated/api_samples/os-extended-floating-ips/floating-ips-get-resp.xml.tpl new file mode 100644 index 000000000000..e0f68ef503a6 --- /dev/null +++ b/nova/tests/integrated/api_samples/os-extended-floating-ips/floating-ips-get-resp.xml.tpl @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/nova/tests/integrated/api_samples/os-extended-floating-ips/floating-ips-list-empty-resp.json.tpl b/nova/tests/integrated/api_samples/os-extended-floating-ips/floating-ips-list-empty-resp.json.tpl new file mode 100644 index 000000000000..12f118da50dd --- /dev/null +++ b/nova/tests/integrated/api_samples/os-extended-floating-ips/floating-ips-list-empty-resp.json.tpl @@ -0,0 +1,3 @@ +{ + "floating_ips": [] +} diff --git a/nova/tests/integrated/api_samples/os-extended-floating-ips/floating-ips-list-empty-resp.xml.tpl b/nova/tests/integrated/api_samples/os-extended-floating-ips/floating-ips-list-empty-resp.xml.tpl new file mode 100644 index 000000000000..da6f0d4ce993 --- /dev/null +++ b/nova/tests/integrated/api_samples/os-extended-floating-ips/floating-ips-list-empty-resp.xml.tpl @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/nova/tests/integrated/api_samples/os-extended-floating-ips/floating-ips-list-resp.json.tpl b/nova/tests/integrated/api_samples/os-extended-floating-ips/floating-ips-list-resp.json.tpl new file mode 100644 index 000000000000..06f57451c9d8 --- /dev/null +++ b/nova/tests/integrated/api_samples/os-extended-floating-ips/floating-ips-list-resp.json.tpl @@ -0,0 +1,19 @@ +{ + "floating_ips": [ + { + "fixed_ip": null, + "id": 1, + "instance_id": null, + "ip": "10.10.10.1", + "pool": "nova" + }, + { + "fixed_ip": null, + "id": 2, + "instance_id": null, + "ip": "10.10.10.2", + "pool": "nova" + } + ] +} + diff --git a/nova/tests/integrated/api_samples/os-extended-floating-ips/floating-ips-list-resp.xml.tpl b/nova/tests/integrated/api_samples/os-extended-floating-ips/floating-ips-list-resp.xml.tpl new file mode 100644 index 000000000000..bbd0b117ef61 --- /dev/null +++ b/nova/tests/integrated/api_samples/os-extended-floating-ips/floating-ips-list-resp.xml.tpl @@ -0,0 +1,5 @@ + + + + + diff --git a/nova/tests/integrated/test_api_samples.py b/nova/tests/integrated/test_api_samples.py index 188f96055d9a..32ee8816e03e 100644 --- a/nova/tests/integrated/test_api_samples.py +++ b/nova/tests/integrated/test_api_samples.py @@ -83,12 +83,15 @@ class ApiSampleTestBase(integrated_helpers._IntegratedTestBase): extension_name = None def setUp(self): + extends = [] self.flags(use_ipv6=False, osapi_compute_link_prefix=self._get_host(), osapi_glance_link_prefix=self._get_glance_host()) if not self.all_extensions: + if hasattr(self, 'extends_name'): + extends = [self.extends_name] ext = [self.extension_name] if self.extension_name else [] - self.flags(osapi_compute_extension=ext) + self.flags(osapi_compute_extension=ext + extends) super(ApiSampleTestBase, self).setUp() fake_network.stub_compute_with_ips(self.stubs) self.generate_samples = os.getenv('GENERATE_SAMPLES') is not None @@ -1351,10 +1354,21 @@ class FloatingIpsJsonTest(ApiSampleTestBase): self.assertEqual(response.status, 202) +class ExtendedFloatingIpsJsonTest(FloatingIpsJsonTest): + extends_name = ("nova.api.openstack.compute.contrib." + "floating_ips.Floating_ips") + extension_name = ("nova.api.openstack.compute.contrib." + "extended_floating_ips.Extended_floating_ips") + + class FloatingIpsXmlTest(FloatingIpsJsonTest): ctype = 'xml' +class ExtendedFloatingIpsXmlTest(ExtendedFloatingIpsJsonTest): + ctype = 'xml' + + class FloatingIpsBulkJsonTest(ApiSampleTestBase): extension_name = "nova.api.openstack.compute.contrib." \ "floating_ips_bulk.Floating_ips_bulk"