From 4bb34182fe28c89686c8a23ddcfc8e9128d289b5 Mon Sep 17 00:00:00 2001 From: Eli Qiao Date: Fri, 5 Sep 2014 14:11:11 +0800 Subject: [PATCH] Port floating_ips_bulk extention to v2.1 This patch ports floating_ips_bulk extention from v2 to v2.1, and have v2 unit test cases shared between v2.1 and v2. Partially implements blueprint v2-on-v3-api Change-Id: I9444ff9c394d530cb76dd4ac21b51cd4de7ef6dc --- .../floating-ips-bulk-create-req.json | 7 + .../floating-ips-bulk-create-resp.json | 7 + .../floating-ips-bulk-delete-req.json | 3 + .../floating-ips-bulk-delete-resp.json | 3 + .../floating-ips-bulk-list-by-host-resp.json | 11 ++ .../floating-ips-bulk-list-resp.json | 25 +++ etc/nova/policy.json | 2 + .../compute/plugins/v3/floating_ips_bulk.py | 167 ++++++++++++++++++ .../compute/schemas/v3/floating_ips_bulk.py | 52 ++++++ .../compute/contrib/test_floating_ips_bulk.py | 56 +++--- nova/tests/fake_policy.py | 1 + .../floating-ips-bulk-create-req.json.tpl | 7 + .../floating-ips-bulk-create-resp.json.tpl | 7 + .../floating-ips-bulk-delete-req.json.tpl | 3 + .../floating-ips-bulk-delete-resp.json.tpl | 3 + ...oating-ips-bulk-list-by-host-resp.json.tpl | 11 ++ .../floating-ips-bulk-list-resp.json.tpl | 25 +++ .../integrated/v3/test_floating_ips_bulk.py | 86 +++++++++ setup.cfg | 1 + 19 files changed, 454 insertions(+), 23 deletions(-) create mode 100644 doc/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-create-req.json create mode 100644 doc/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-create-resp.json create mode 100644 doc/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-delete-req.json create mode 100644 doc/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-delete-resp.json create mode 100644 doc/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-list-by-host-resp.json create mode 100644 doc/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-list-resp.json create mode 100644 nova/api/openstack/compute/plugins/v3/floating_ips_bulk.py create mode 100644 nova/api/openstack/compute/schemas/v3/floating_ips_bulk.py create mode 100644 nova/tests/integrated/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-create-req.json.tpl create mode 100644 nova/tests/integrated/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-create-resp.json.tpl create mode 100644 nova/tests/integrated/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-delete-req.json.tpl create mode 100644 nova/tests/integrated/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-delete-resp.json.tpl create mode 100644 nova/tests/integrated/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-list-by-host-resp.json.tpl create mode 100644 nova/tests/integrated/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-list-resp.json.tpl create mode 100644 nova/tests/integrated/v3/test_floating_ips_bulk.py diff --git a/doc/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-create-req.json b/doc/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-create-req.json new file mode 100644 index 0000000000..d5403b7d88 --- /dev/null +++ b/doc/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-create-req.json @@ -0,0 +1,7 @@ +{ + "floating_ips_bulk_create": { + "ip_range": "192.168.1.0/24" + "pool": "nova", + "interface": "eth0" + } +} diff --git a/doc/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-create-resp.json b/doc/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-create-resp.json new file mode 100644 index 0000000000..ef1cbfb17f --- /dev/null +++ b/doc/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-create-resp.json @@ -0,0 +1,7 @@ +{ + "floating_ips_bulk_create": { + "interface": "eth0", + "ip_range": "192.168.1.0/24", + "pool": "nova" + } +} \ No newline at end of file diff --git a/doc/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-delete-req.json b/doc/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-delete-req.json new file mode 100644 index 0000000000..df59c1a735 --- /dev/null +++ b/doc/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-delete-req.json @@ -0,0 +1,3 @@ +{ + "ip_range": "192.168.1.0/24" +} \ No newline at end of file diff --git a/doc/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-delete-resp.json b/doc/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-delete-resp.json new file mode 100644 index 0000000000..166984b24a --- /dev/null +++ b/doc/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-delete-resp.json @@ -0,0 +1,3 @@ +{ + "floating_ips_bulk_delete": "192.168.1.0/24" +} \ No newline at end of file diff --git a/doc/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-list-by-host-resp.json b/doc/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-list-by-host-resp.json new file mode 100644 index 0000000000..0eaaf75ae0 --- /dev/null +++ b/doc/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-list-by-host-resp.json @@ -0,0 +1,11 @@ +{ + "floating_ip_info": [ + { + "address": "10.10.10.3", + "instance_uuid": null, + "interface": "eth0", + "pool": "nova", + "project_id": null + } + ] +} \ No newline at end of file diff --git a/doc/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-list-resp.json b/doc/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-list-resp.json new file mode 100644 index 0000000000..de1e622bb1 --- /dev/null +++ b/doc/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-list-resp.json @@ -0,0 +1,25 @@ +{ + "floating_ip_info": [ + { + "address": "10.10.10.1", + "instance_uuid": null, + "interface": "eth0", + "pool": "nova", + "project_id": null + }, + { + "address": "10.10.10.2", + "instance_uuid": null, + "interface": "eth0", + "pool": "nova", + "project_id": null + }, + { + "address": "10.10.10.3", + "instance_uuid": null, + "interface": "eth0", + "pool": "nova", + "project_id": null + } + ] +} \ No newline at end of file diff --git a/etc/nova/policy.json b/etc/nova/policy.json index 80f42427f9..54d7267a1d 100644 --- a/etc/nova/policy.json +++ b/etc/nova/policy.json @@ -158,6 +158,8 @@ "compute_extension:v3:os-floating-ip-pools:discoverable": "", "compute_extension:floating_ips": "", "compute_extension:floating_ips_bulk": "rule:admin_api", + "compute_extension:v3:os-floating-ips-bulk": "rule_admin_api", + "compute_extension:v3:os-floating-ips-bulk:discoverable": "", "compute_extension:fping": "", "compute_extension:fping:all_tenants": "rule:admin_api", "compute_extension:v3:os-fping": "", diff --git a/nova/api/openstack/compute/plugins/v3/floating_ips_bulk.py b/nova/api/openstack/compute/plugins/v3/floating_ips_bulk.py new file mode 100644 index 0000000000..e5d6d1d710 --- /dev/null +++ b/nova/api/openstack/compute/plugins/v3/floating_ips_bulk.py @@ -0,0 +1,167 @@ +# Copyright 2012 IBM Corp. +# +# 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. + +import netaddr +from oslo.config import cfg +import six +import webob.exc + +from nova.api.openstack.compute.schemas.v3 import floating_ips_bulk +from nova.api.openstack import extensions +from nova.api import validation +from nova import exception +from nova.i18n import _ +from nova import objects + +CONF = cfg.CONF +CONF.import_opt('default_floating_pool', 'nova.network.floating_ips') +CONF.import_opt('public_interface', 'nova.network.linux_net') + + +ALIAS = 'os-floating-ips-bulk' +authorize = extensions.extension_authorizer('compute', 'v3:' + ALIAS) + + +class FloatingIPBulkController(object): + + @extensions.expected_errors(404) + def index(self, req): + """Return a list of all floating ips.""" + context = req.environ['nova.context'] + authorize(context) + + return self._get_floating_ip_info(context) + + @extensions.expected_errors(404) + def show(self, req, id): + """Return a list of all floating ips for a given host.""" + context = req.environ['nova.context'] + authorize(context) + + return self._get_floating_ip_info(context, id) + + def _get_floating_ip_info(self, context, host=None): + floating_ip_info = {"floating_ip_info": []} + + if host is None: + try: + floating_ips = objects.FloatingIPList.get_all(context) + except exception.NoFloatingIpsDefined: + return floating_ip_info + else: + try: + floating_ips = objects.FloatingIPList.get_by_host(context, + host) + except exception.FloatingIpNotFoundForHost as e: + raise webob.exc.HTTPNotFound(explanation=e.format_message()) + + for floating_ip in floating_ips: + instance_uuid = None + if floating_ip.fixed_ip: + instance_uuid = floating_ip.fixed_ip.instance_uuid + + result = {'address': str(floating_ip['address']), + 'pool': floating_ip['pool'], + 'interface': floating_ip['interface'], + 'project_id': floating_ip['project_id'], + 'instance_uuid': instance_uuid} + floating_ip_info['floating_ip_info'].append(result) + + return floating_ip_info + + @extensions.expected_errors(400) + @validation.schema(floating_ips_bulk.create) + def create(self, req, body): + """Bulk create floating ips.""" + context = req.environ['nova.context'] + authorize(context) + + params = body['floating_ips_bulk_create'] + ip_range = params['ip_range'] + + pool = params.get('pool', CONF.default_floating_pool) + interface = params.get('interface', CONF.public_interface) + + try: + ips = [objects.FloatingIPList.make_ip_info(addr, pool, interface) + for addr in self._address_to_hosts(ip_range)] + except exception.InvalidInput as exc: + raise webob.exc.HTTPBadRequest(explanation=exc.format_message()) + + try: + objects.FloatingIPList.create(context, ips) + except exception.FloatingIpExists as exc: + raise webob.exc.HTTPBadRequest(explanation=exc.format_message()) + + return {"floating_ips_bulk_create": {"ip_range": ip_range, + "pool": pool, + "interface": interface}} + + @extensions.expected_errors((400, 404)) + @validation.schema(floating_ips_bulk.delete) + def update(self, req, id, body): + """Bulk delete floating IPs.""" + context = req.environ['nova.context'] + authorize(context) + + if id != "delete": + msg = _("Unknown action") + raise webob.exc.HTTPNotFound(explanation=msg) + ip_range = body['ip_range'] + try: + ips = (objects.FloatingIPList.make_ip_info(address, None, None) + for address in self._address_to_hosts(ip_range)) + except exception.InvalidInput as exc: + raise webob.exc.HTTPBadRequest(explanation=exc.format_message()) + objects.FloatingIPList.destroy(context, ips) + + return {"floating_ips_bulk_delete": ip_range} + + def _address_to_hosts(self, addresses): + """Iterate over hosts within an address range. + + If an explicit range specifier is missing, the parameter is + interpreted as a specific individual address. + """ + try: + return [netaddr.IPAddress(addresses)] + except ValueError: + net = netaddr.IPNetwork(addresses) + if net.size < 4: + reason = _("/%s should be specified as single address(es) " + "not in cidr format") % net.prefixlen + raise exception.InvalidInput(reason=reason) + else: + return net.iter_hosts() + except netaddr.AddrFormatError as exc: + raise exception.InvalidInput(reason=six.text_type(exc)) + + +class FloatingIpsBulk(extensions.V3APIExtensionBase): + """Bulk handling of Floating IPs.""" + + name = "FloatingIpsBulk" + alias = ALIAS + version = 1 + + def get_resources(self): + resource = [extensions.ResourceExtension(ALIAS, + FloatingIPBulkController())] + return resource + + def get_controller_extensions(self): + """It's an abstract function V3APIExtensionBase and the extension + will not be loaded without it. + """ + return [] diff --git a/nova/api/openstack/compute/schemas/v3/floating_ips_bulk.py b/nova/api/openstack/compute/schemas/v3/floating_ips_bulk.py new file mode 100644 index 0000000000..2f48495684 --- /dev/null +++ b/nova/api/openstack/compute/schemas/v3/floating_ips_bulk.py @@ -0,0 +1,52 @@ +# Copyright 2014 IBM 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. + + +ip_range = { + # TODO(eliqiao) need to find a better pattern + 'type': 'string', + 'pattern': '^[0-9./a-fA-F]*$', +} + +create = { + 'type': 'object', + 'properties': { + 'floating_ips_bulk_create': { + 'type': 'object', + 'properties': { + 'ip_range': ip_range, + 'pool': { + 'type': 'string', 'minLength': 1, 'maxLength': 255, + }, + 'interface': { + 'type': 'string', 'minLength': 1, 'maxLength': 255, + }, + }, + 'required': ['ip_range'], + 'additionalProperties': False, + }, + }, + 'required': ['floating_ips_bulk_create'], + 'additionalProperties': False, +} + + +delete = { + 'type': 'object', + 'properties': { + 'ip_range': ip_range, + }, + 'required': ['ip_range'], + 'additionalProperties': False, +} diff --git a/nova/tests/api/openstack/compute/contrib/test_floating_ips_bulk.py b/nova/tests/api/openstack/compute/contrib/test_floating_ips_bulk.py index 1142a74d9f..bac9ea66db 100644 --- a/nova/tests/api/openstack/compute/contrib/test_floating_ips_bulk.py +++ b/nova/tests/api/openstack/compute/contrib/test_floating_ips_bulk.py @@ -16,26 +16,34 @@ import netaddr from oslo.config import cfg import webob -from nova.api.openstack.compute.contrib import floating_ips_bulk +from nova.api.openstack.compute.contrib import floating_ips_bulk as fipbulk_v2 +from nova.api.openstack.compute.plugins.v3 import floating_ips_bulk as\ + fipbulk_v21 from nova import context +from nova import exception from nova import test from nova.tests.api.openstack import fakes CONF = cfg.CONF -class FloatingIpsBulk(test.TestCase): +class FloatingIPBulkV21(test.TestCase): + + floating_ips_bulk = fipbulk_v21 + url = '/v2/fake/os-floating-ips-bulk' + delete_url = '/v2/fake/os-fixed-ips/delete' + bad_request = exception.ValidationError def setUp(self): - super(FloatingIpsBulk, self).setUp() + super(FloatingIPBulkV21, self).setUp() self.context = context.get_admin_context() - self.controller = floating_ips_bulk.FloatingIPBulkController() + self.controller = self.floating_ips_bulk.FloatingIPBulkController() def _setup_floating_ips(self, ip_range): body = {'floating_ips_bulk_create': {'ip_range': ip_range}} - req = fakes.HTTPRequest.blank('/v2/fake/os-floating-ips-bulk') - res_dict = self.controller.create(req, body) + req = fakes.HTTPRequest.blank(self.url) + res_dict = self.controller.create(req, body=body) response = {"floating_ips_bulk_create": { 'ip_range': ip_range, 'pool': CONF.default_floating_pool, @@ -52,8 +60,8 @@ class FloatingIpsBulk(test.TestCase): body = {'floating_ips_bulk_create': {'ip_range': ip_range, 'pool': pool}} - req = fakes.HTTPRequest.blank('/v2/fake/os-floating-ips-bulk') - res_dict = self.controller.create(req, body) + req = fakes.HTTPRequest.blank(self.url) + res_dict = self.controller.create(req, body=body) response = {"floating_ips_bulk_create": { 'ip_range': ip_range, 'pool': pool, @@ -63,8 +71,7 @@ class FloatingIpsBulk(test.TestCase): def test_list_ips(self): ip_range = '192.168.1.1/28' self._setup_floating_ips(ip_range) - req = fakes.HTTPRequest.blank('/v2/fake/os-floating-ips-bulk', - use_admin_context=True) + req = fakes.HTTPRequest.blank(self.url, use_admin_context=True) res_dict = self.controller.index(req) ip_info = [{'address': str(ip_addr), @@ -80,8 +87,7 @@ class FloatingIpsBulk(test.TestCase): def test_list_ip_by_host(self): ip_range = '192.168.1.1/28' self._setup_floating_ips(ip_range) - req = fakes.HTTPRequest.blank('/v2/fake/os-floating-ips-bulk', - use_admin_context=True) + req = fakes.HTTPRequest.blank(self.url, use_admin_context=True) self.assertRaises(webob.exc.HTTPNotFound, self.controller.show, req, 'host') @@ -90,15 +96,14 @@ class FloatingIpsBulk(test.TestCase): self._setup_floating_ips(ip_range) body = {'ip_range': ip_range} - req = fakes.HTTPRequest.blank('/v2/fake/os-fixed-ips/delete') - res_dict = self.controller.update(req, "delete", body) + req = fakes.HTTPRequest.blank(self.delete_url) + res_dict = self.controller.update(req, "delete", body=body) response = {"floating_ips_bulk_delete": ip_range} self.assertEqual(res_dict, response) # Check that the IPs are actually deleted - req = fakes.HTTPRequest.blank('/v2/fake/os-floating-ips-bulk', - use_admin_context=True) + req = fakes.HTTPRequest.blank(self.url, use_admin_context=True) res_dict = self.controller.index(req) response = {'floating_ip_info': []} self.assertEqual(res_dict, response) @@ -109,21 +114,26 @@ class FloatingIpsBulk(test.TestCase): ip_range = '192.168.1.0/28' body = {'floating_ips_bulk_create': {'ip_range': ip_range}} - req = fakes.HTTPRequest.blank('/v2/fake/os-floating-ips-bulk') + req = fakes.HTTPRequest.blank(self.url) self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create, - req, body) + req, body=body) def test_create_bad_cidr_fail(self): # netaddr can't handle /32 or 31 cidrs ip_range = '192.168.1.1/32' body = {'floating_ips_bulk_create': {'ip_range': ip_range}} - req = fakes.HTTPRequest.blank('/v2/fake/os-floating-ips-bulk') + req = fakes.HTTPRequest.blank(self.url) self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create, - req, body) + req, body=body) def test_create_invalid_cidr_fail(self): ip_range = 'not a cidr' body = {'floating_ips_bulk_create': {'ip_range': ip_range}} - req = fakes.HTTPRequest.blank('/v2/fake/os-floating-ips-bulk') - self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create, - req, body) + req = fakes.HTTPRequest.blank(self.url) + self.assertRaises(self.bad_request, self.controller.create, + req, body=body) + + +class FloatingIPBulkV2(FloatingIPBulkV21): + floating_ips_bulk = fipbulk_v2 + bad_request = webob.exc.HTTPBadRequest diff --git a/nova/tests/fake_policy.py b/nova/tests/fake_policy.py index 7321ff1189..81a69c54a4 100644 --- a/nova/tests/fake_policy.py +++ b/nova/tests/fake_policy.py @@ -216,6 +216,7 @@ policy_data = """ "compute_extension:v3:os-floating-ip-pools": "", "compute_extension:floating_ips": "", "compute_extension:floating_ips_bulk": "", + "compute_extension:v3:os-floating-ips-bulk": "", "compute_extension:fping": "", "compute_extension:fping:all_tenants": "is_admin:True", "compute_extension:v3:os-fping": "", diff --git a/nova/tests/integrated/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-create-req.json.tpl b/nova/tests/integrated/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-create-req.json.tpl new file mode 100644 index 0000000000..2f16cf07cb --- /dev/null +++ b/nova/tests/integrated/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-create-req.json.tpl @@ -0,0 +1,7 @@ +{ + "floating_ips_bulk_create": { + "ip_range": "%(ip_range)s", + "pool": "%(pool)s", + "interface": "%(interface)s" + } +} diff --git a/nova/tests/integrated/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-create-resp.json.tpl b/nova/tests/integrated/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-create-resp.json.tpl new file mode 100644 index 0000000000..ef1cbfb17f --- /dev/null +++ b/nova/tests/integrated/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-create-resp.json.tpl @@ -0,0 +1,7 @@ +{ + "floating_ips_bulk_create": { + "interface": "eth0", + "ip_range": "192.168.1.0/24", + "pool": "nova" + } +} \ No newline at end of file diff --git a/nova/tests/integrated/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-delete-req.json.tpl b/nova/tests/integrated/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-delete-req.json.tpl new file mode 100644 index 0000000000..d630d669cd --- /dev/null +++ b/nova/tests/integrated/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-delete-req.json.tpl @@ -0,0 +1,3 @@ +{ + "ip_range": "%(ip_range)s" +} diff --git a/nova/tests/integrated/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-delete-resp.json.tpl b/nova/tests/integrated/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-delete-resp.json.tpl new file mode 100644 index 0000000000..166984b24a --- /dev/null +++ b/nova/tests/integrated/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-delete-resp.json.tpl @@ -0,0 +1,3 @@ +{ + "floating_ips_bulk_delete": "192.168.1.0/24" +} \ No newline at end of file diff --git a/nova/tests/integrated/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-list-by-host-resp.json.tpl b/nova/tests/integrated/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-list-by-host-resp.json.tpl new file mode 100644 index 0000000000..0eaaf75ae0 --- /dev/null +++ b/nova/tests/integrated/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-list-by-host-resp.json.tpl @@ -0,0 +1,11 @@ +{ + "floating_ip_info": [ + { + "address": "10.10.10.3", + "instance_uuid": null, + "interface": "eth0", + "pool": "nova", + "project_id": null + } + ] +} \ No newline at end of file diff --git a/nova/tests/integrated/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-list-resp.json.tpl b/nova/tests/integrated/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-list-resp.json.tpl new file mode 100644 index 0000000000..de1e622bb1 --- /dev/null +++ b/nova/tests/integrated/v3/api_samples/os-floating-ips-bulk/floating-ips-bulk-list-resp.json.tpl @@ -0,0 +1,25 @@ +{ + "floating_ip_info": [ + { + "address": "10.10.10.1", + "instance_uuid": null, + "interface": "eth0", + "pool": "nova", + "project_id": null + }, + { + "address": "10.10.10.2", + "instance_uuid": null, + "interface": "eth0", + "pool": "nova", + "project_id": null + }, + { + "address": "10.10.10.3", + "instance_uuid": null, + "interface": "eth0", + "pool": "nova", + "project_id": null + } + ] +} \ No newline at end of file diff --git a/nova/tests/integrated/v3/test_floating_ips_bulk.py b/nova/tests/integrated/v3/test_floating_ips_bulk.py new file mode 100644 index 0000000000..630902572d --- /dev/null +++ b/nova/tests/integrated/v3/test_floating_ips_bulk.py @@ -0,0 +1,86 @@ +# Copyright 2014 IBM Corp. +# +# +# 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.config import cfg + +from nova import context +from nova.tests.integrated.v3 import api_sample_base + +CONF = cfg.CONF +CONF.import_opt('default_floating_pool', 'nova.network.floating_ips') +CONF.import_opt('public_interface', 'nova.network.linux_net') + + +class FloatingIpsBulkTest(api_sample_base.ApiSampleTestBaseV3): + extension_name = "os-floating-ips-bulk" + + def setUp(self): + super(FloatingIpsBulkTest, 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, + 'host': "testHost" + }, + ] + self.compute.db.floating_ip_bulk_create( + context.get_admin_context(), self.ip_pool) + + self.addCleanup(self.compute.db.floating_ip_bulk_destroy, + context.get_admin_context(), self.ip_pool) + + def test_floating_ips_bulk_list(self): + response = self._do_get('os-floating-ips-bulk') + subs = self._get_regexes() + self._verify_response('floating-ips-bulk-list-resp', + subs, response, 200) + + def test_floating_ips_bulk_list_by_host(self): + response = self._do_get('os-floating-ips-bulk/testHost') + subs = self._get_regexes() + self._verify_response('floating-ips-bulk-list-by-host-resp', + subs, response, 200) + + def test_floating_ips_bulk_create(self): + response = self._do_post('os-floating-ips-bulk', + 'floating-ips-bulk-create-req', + {"ip_range": "192.168.1.0/24", + "pool": CONF.default_floating_pool, + "interface": CONF.public_interface}) + subs = self._get_regexes() + self._verify_response('floating-ips-bulk-create-resp', subs, + response, 200) + + def test_floating_ips_bulk_delete(self): + response = self._do_put('os-floating-ips-bulk/delete', + 'floating-ips-bulk-delete-req', + {"ip_range": "192.168.1.0/24"}) + subs = self._get_regexes() + self._verify_response('floating-ips-bulk-delete-resp', subs, + response, 200) diff --git a/setup.cfg b/setup.cfg index 48b8008303..f824819cad 100644 --- a/setup.cfg +++ b/setup.cfg @@ -86,6 +86,7 @@ nova.api.v3.extensions = flavor_rxtx = nova.api.openstack.compute.plugins.v3.flavor_rxtx:FlavorRxtx flavor_manage = nova.api.openstack.compute.plugins.v3.flavor_manage:FlavorManage floating_ip_pools = nova.api.openstack.compute.plugins.v3.floating_ip_pools:FloatingIpPools + floating_ips_bulk = nova.api.openstack.compute.plugins.v3.floating_ips_bulk:FloatingIpsBulk fping = nova.api.openstack.compute.plugins.v3.fping:Fping hide_server_addresses = nova.api.openstack.compute.plugins.v3.hide_server_addresses:HideServerAddresses hosts = nova.api.openstack.compute.plugins.v3.hosts:Hosts