diff --git a/doc/api_samples/os-floating-ips-bulk/floating-ips-bulk-create-req.json b/doc/api_samples/os-floating-ips-bulk/floating-ips-bulk-create-req.json new file mode 100644 index 000000000000..d174bad5abc0 --- /dev/null +++ b/doc/api_samples/os-floating-ips-bulk/floating-ips-bulk-create-req.json @@ -0,0 +1,8 @@ +{ + "floating_ips_bulk_create" : + { + "ip_range": "192.168.1.0/24", + "pool": "nova", + "interface": "eth0" + } +} \ No newline at end of file diff --git a/doc/api_samples/os-floating-ips-bulk/floating-ips-bulk-create-req.xml b/doc/api_samples/os-floating-ips-bulk/floating-ips-bulk-create-req.xml new file mode 100644 index 000000000000..1fc7305090d2 --- /dev/null +++ b/doc/api_samples/os-floating-ips-bulk/floating-ips-bulk-create-req.xml @@ -0,0 +1,6 @@ + + +192.168.1.0/24 +nova +eth0 + \ No newline at end of file diff --git a/doc/api_samples/os-floating-ips-bulk/floating-ips-bulk-create-resp.json b/doc/api_samples/os-floating-ips-bulk/floating-ips-bulk-create-resp.json new file mode 100644 index 000000000000..ef1cbfb17f31 --- /dev/null +++ b/doc/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/api_samples/os-floating-ips-bulk/floating-ips-bulk-create-resp.xml b/doc/api_samples/os-floating-ips-bulk/floating-ips-bulk-create-resp.xml new file mode 100644 index 000000000000..db80bbfc10fd --- /dev/null +++ b/doc/api_samples/os-floating-ips-bulk/floating-ips-bulk-create-resp.xml @@ -0,0 +1,6 @@ + + + eth0 + 192.168.1.0/24 + nova + \ No newline at end of file diff --git a/doc/api_samples/os-floating-ips-bulk/floating-ips-bulk-delete-req.json b/doc/api_samples/os-floating-ips-bulk/floating-ips-bulk-delete-req.json new file mode 100644 index 000000000000..df59c1a73599 --- /dev/null +++ b/doc/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/api_samples/os-floating-ips-bulk/floating-ips-bulk-delete-req.xml b/doc/api_samples/os-floating-ips-bulk/floating-ips-bulk-delete-req.xml new file mode 100644 index 000000000000..c40f28dc3489 --- /dev/null +++ b/doc/api_samples/os-floating-ips-bulk/floating-ips-bulk-delete-req.xml @@ -0,0 +1,2 @@ + +192.168.1.0/24 \ No newline at end of file diff --git a/doc/api_samples/os-floating-ips-bulk/floating-ips-bulk-delete-resp.json b/doc/api_samples/os-floating-ips-bulk/floating-ips-bulk-delete-resp.json new file mode 100644 index 000000000000..166984b24a4f --- /dev/null +++ b/doc/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/api_samples/os-floating-ips-bulk/floating-ips-bulk-delete-resp.xml b/doc/api_samples/os-floating-ips-bulk/floating-ips-bulk-delete-resp.xml new file mode 100644 index 000000000000..3d77af334a56 --- /dev/null +++ b/doc/api_samples/os-floating-ips-bulk/floating-ips-bulk-delete-resp.xml @@ -0,0 +1,2 @@ + +192.168.1.0/24 \ No newline at end of file diff --git a/doc/api_samples/os-floating-ips-bulk/floating-ips-bulk-list-by-host-resp.json b/doc/api_samples/os-floating-ips-bulk/floating-ips-bulk-list-by-host-resp.json new file mode 100644 index 000000000000..0eaaf75ae098 --- /dev/null +++ b/doc/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/api_samples/os-floating-ips-bulk/floating-ips-bulk-list-by-host-resp.xml b/doc/api_samples/os-floating-ips-bulk/floating-ips-bulk-list-by-host-resp.xml new file mode 100644 index 000000000000..4c3c8cd9cae2 --- /dev/null +++ b/doc/api_samples/os-floating-ips-bulk/floating-ips-bulk-list-by-host-resp.xml @@ -0,0 +1,10 @@ + + + + eth0 + None + None + nova +
10.10.10.3
+
+
\ No newline at end of file diff --git a/doc/api_samples/os-floating-ips-bulk/floating-ips-bulk-list-resp.json b/doc/api_samples/os-floating-ips-bulk/floating-ips-bulk-list-resp.json new file mode 100644 index 000000000000..de1e622bb163 --- /dev/null +++ b/doc/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/doc/api_samples/os-floating-ips-bulk/floating-ips-bulk-list-resp.xml b/doc/api_samples/os-floating-ips-bulk/floating-ips-bulk-list-resp.xml new file mode 100644 index 000000000000..6ef85bd87411 --- /dev/null +++ b/doc/api_samples/os-floating-ips-bulk/floating-ips-bulk-list-resp.xml @@ -0,0 +1,24 @@ + + + + eth0 + None + None + nova +
10.10.10.1
+
+ + eth0 + None + None + nova +
10.10.10.2
+
+ + eth0 + None + None + nova +
10.10.10.3
+
+
\ No newline at end of file diff --git a/etc/nova/policy.json b/etc/nova/policy.json index cf4864650014..857613edc5e4 100644 --- a/etc/nova/policy.json +++ b/etc/nova/policy.json @@ -48,6 +48,7 @@ "compute_extension:floating_ip_dns": "", "compute_extension:floating_ip_pools": "", "compute_extension:floating_ips": "", + "compute_extension:floating_ips_bulk": "rule:admin_api", "compute_extension:fping": "", "compute_extension:fping:all_tenants": "rule:admin_api", "compute_extension:hosts": "rule:admin_api", diff --git a/nova/api/openstack/compute/contrib/floating_ips_bulk.py b/nova/api/openstack/compute/contrib/floating_ips_bulk.py new file mode 100644 index 000000000000..59d9d24b6c29 --- /dev/null +++ b/nova/api/openstack/compute/contrib/floating_ips_bulk.py @@ -0,0 +1,176 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2012 IBM +# 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. + +import netaddr +import urllib +import webob.exc + +from nova.api.openstack import extensions +from nova.api.openstack import wsgi +from nova.api.openstack import xmlutil +from nova import db +from nova import exception +from nova.openstack.common import cfg +from nova.openstack.common import log as logging + +CONF = cfg.CONF +CONF.import_opt('default_floating_pool', 'nova.network.manager') +CONF.import_opt('public_interface', 'nova.network.linux_net') + + +LOG = logging.getLogger(__name__) +authorize = extensions.extension_authorizer('compute', 'floating_ips_bulk') + + +class FloatingIPBulkController(object): + + 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) + + 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": []} + + try: + if host is None: + floating_ips = db.floating_ip_get_all(context) + else: + floating_ips = db.floating_ip_get_all_by_host(context, host) + except exception.NoFloatingIpsDefined: + return floating_ip_info + + for floating_ip in floating_ips: + instance_uuid = None + if floating_ip['fixed_ip_id']: + fixed_ip = db.fixed_ip_get(context, floating_ip['fixed_ip_id']) + instance_uuid = fixed_ip['instance_uuid'] + + result = {'address': 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 + + def create(self, req, body): + """Bulk create floating ips""" + context = req.environ['nova.context'] + authorize(context) + + if not 'floating_ips_bulk_create' in body: + raise webob.exc.HTTPUnprocessableEntity() + params = body['floating_ips_bulk_create'] + + LOG.debug(params) + + if not 'ip_range' in params: + raise webob.exc.HTTPUnprocessableEntity() + ip_range = params['ip_range'] + + pool = params.get('pool', CONF.default_floating_pool) + interface = params.get('interface', CONF.public_interface) + + try: + ips = ({'address': str(address), + 'pool': pool, + 'interface': interface} + for address in self._address_to_hosts(ip_range)) + except exception.InvalidInput as exc: + raise webob.exc.HTTPBadRequest(explanation=str(exc)) + + try: + db.floating_ip_bulk_create(context, ips) + except exception.FloatingIpExists as exc: + raise webob.exc.HTTPBadRequest(explanation=str(exc)) + + return {"floating_ips_bulk_create": {"ip_range": ip_range, + "pool": pool, + "interface": interface}} + + def update(self, req, id, body): + """Bulk delete floating IPs""" + context = req.environ['nova.context'] + authorize(context) + + if id != "delete": + raise webob.exc.HTTPNotFound("Unknown action") + + try: + ip_range = body['ip_range'] + except (TypeError, KeyError): + raise webob.exc.HTTPUnprocessableEntity() + + try: + ips = ({'address': str(address)} + for address in self._address_to_hosts(ip_range)) + except exception.InvalidInput as exc: + raise webob.exc.HTTPBadRequest(explanation=str(exc)) + db.floating_ip_bulk_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=str(exc)) + + +class Floating_ips_bulk(extensions.ExtensionDescriptor): + """Bulk handling of Floating IPs""" + + name = "FloatingIpsBulk" + alias = "os-floating-ips-bulk" + namespace = ("http://docs.openstack.org/compute/ext/" + "floating_ips_bulk/api/v2") + updated = "2012-10-29T13:25:27-06:00" + + def __init__(self, ext_mgr): + ext_mgr.register(self) + + def get_resources(self): + resources = [] + resource = extensions.ResourceExtension('os-floating-ips-bulk', + FloatingIPBulkController()) + resources.append(resource) + return resources diff --git a/nova/tests/api/openstack/compute/contrib/test_floating_ip_bulk.py b/nova/tests/api/openstack/compute/contrib/test_floating_ip_bulk.py new file mode 100644 index 000000000000..2dd3cc2177b4 --- /dev/null +++ b/nova/tests/api/openstack/compute/contrib/test_floating_ip_bulk.py @@ -0,0 +1,127 @@ +# Copyright 2012 IBM +# 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. + +import netaddr +import webob + +from nova.api.openstack.compute.contrib import floating_ips_bulk +from nova import context +from nova import db +from nova import exception +from nova.openstack.common import cfg +from nova import test +from nova.tests.api.openstack import fakes + +CONF = cfg.CONF + + +class FloatingIPBulk(test.TestCase): + + def setUp(self): + super(FloatingIPBulk, self).setUp() + + self.context = context.get_admin_context() + self.controller = floating_ips_bulk.FloatingIPBulkController() + + def tearDown(self): + super(FloatingIPBulk, self).tearDown() + + 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) + response = {"floating_ips_bulk_create": { + 'ip_range': ip_range, + 'pool': CONF.default_floating_pool, + 'interface': CONF.public_interface}} + self.assertEqual(res_dict, response) + + def test_create_ips(self): + ip_range = '192.168.1.0/24' + self._setup_floating_ips(ip_range) + + def test_create_ips_pool(self): + ip_range = '10.0.1.0/20' + pool = 'a new pool' + 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) + response = {"floating_ips_bulk_create": { + 'ip_range': ip_range, + 'pool': pool, + 'interface': CONF.public_interface}} + self.assertEqual(res_dict, response) + + 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) + res_dict = self.controller.index(req) + + ip_info = [{'address': str(ip_addr), + 'pool': CONF.default_floating_pool, + 'interface': CONF.public_interface, + 'project_id': None, + 'instance_uuid': None} + for ip_addr in netaddr.IPNetwork(ip_range).iter_hosts()] + response = {'floating_ip_info': ip_info} + + self.assertEqual(res_dict, response) + + def test_delete_ips(self): + ip_range = '192.168.1.0/20' + 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) + + 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) + res_dict = self.controller.index(req) + response = {'floating_ip_info': []} + self.assertEqual(res_dict, response) + + def test_create_duplicate_fail(self): + ip_range = '192.168.1.0/20' + self._setup_floating_ips(ip_range) + + 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') + self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create, + req, 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') + self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create, + req, 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) diff --git a/nova/tests/api/openstack/compute/test_extensions.py b/nova/tests/api/openstack/compute/test_extensions.py index e71833916285..82278c4fc1ad 100644 --- a/nova/tests/api/openstack/compute/test_extensions.py +++ b/nova/tests/api/openstack/compute/test_extensions.py @@ -178,6 +178,7 @@ class ExtensionControllerTest(ExtensionTestCase): "FloatingIps", "FloatingIpDns", "FloatingIpPools", + "FloatingIpsBulk", "Fox In Socks", "Hosts", "Keypairs", 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 531508951553..6ac33b933322 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 @@ -208,6 +208,14 @@ "namespace": "http://docs.openstack.org/compute/ext/floating_ips/api/v1.1", "updated": "%(timestamp)s" }, + { + "alias": "os-floating-ips-bulk", + "description": "%(text)s", + "links": [], + "name": "FloatingIpsBulk", + "namespace": "http://docs.openstack.org/compute/ext/floating_ips_bulk/api/v2", + "updated": "%(timestamp)s" + }, { "alias": "os-hosts", "description": "%(text)s", 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 5f58cc7d7836..1fca0eb2c193 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 @@ -78,6 +78,9 @@ %(text)s + + %(text)s + %(text)s diff --git a/nova/tests/integrated/api_samples/os-floating-ips-bulk/floating-ips-bulk-create-req.json.tpl b/nova/tests/integrated/api_samples/os-floating-ips-bulk/floating-ips-bulk-create-req.json.tpl new file mode 100644 index 000000000000..676859de9de9 --- /dev/null +++ b/nova/tests/integrated/api_samples/os-floating-ips-bulk/floating-ips-bulk-create-req.json.tpl @@ -0,0 +1,8 @@ +{ + "floating_ips_bulk_create" : + { + "ip_range": "%(ip_range)s", + "pool": "%(pool)s", + "interface": "%(interface)s" + } +} diff --git a/nova/tests/integrated/api_samples/os-floating-ips-bulk/floating-ips-bulk-create-req.xml.tpl b/nova/tests/integrated/api_samples/os-floating-ips-bulk/floating-ips-bulk-create-req.xml.tpl new file mode 100644 index 000000000000..ebe0b9aa9aea --- /dev/null +++ b/nova/tests/integrated/api_samples/os-floating-ips-bulk/floating-ips-bulk-create-req.xml.tpl @@ -0,0 +1,6 @@ + + +%(ip_range)s +%(pool)s +%(interface)s + diff --git a/nova/tests/integrated/api_samples/os-floating-ips-bulk/floating-ips-bulk-create-resp.json.tpl b/nova/tests/integrated/api_samples/os-floating-ips-bulk/floating-ips-bulk-create-resp.json.tpl new file mode 100644 index 000000000000..ef1cbfb17f31 --- /dev/null +++ b/nova/tests/integrated/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/api_samples/os-floating-ips-bulk/floating-ips-bulk-create-resp.xml.tpl b/nova/tests/integrated/api_samples/os-floating-ips-bulk/floating-ips-bulk-create-resp.xml.tpl new file mode 100644 index 000000000000..db80bbfc10fd --- /dev/null +++ b/nova/tests/integrated/api_samples/os-floating-ips-bulk/floating-ips-bulk-create-resp.xml.tpl @@ -0,0 +1,6 @@ + + + eth0 + 192.168.1.0/24 + nova + \ No newline at end of file diff --git a/nova/tests/integrated/api_samples/os-floating-ips-bulk/floating-ips-bulk-delete-req.json.tpl b/nova/tests/integrated/api_samples/os-floating-ips-bulk/floating-ips-bulk-delete-req.json.tpl new file mode 100644 index 000000000000..d630d669cda3 --- /dev/null +++ b/nova/tests/integrated/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/api_samples/os-floating-ips-bulk/floating-ips-bulk-delete-req.xml.tpl b/nova/tests/integrated/api_samples/os-floating-ips-bulk/floating-ips-bulk-delete-req.xml.tpl new file mode 100644 index 000000000000..27a6b0e95a9e --- /dev/null +++ b/nova/tests/integrated/api_samples/os-floating-ips-bulk/floating-ips-bulk-delete-req.xml.tpl @@ -0,0 +1,2 @@ + +%(ip_range)s diff --git a/nova/tests/integrated/api_samples/os-floating-ips-bulk/floating-ips-bulk-delete-resp.json.tpl b/nova/tests/integrated/api_samples/os-floating-ips-bulk/floating-ips-bulk-delete-resp.json.tpl new file mode 100644 index 000000000000..166984b24a4f --- /dev/null +++ b/nova/tests/integrated/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/api_samples/os-floating-ips-bulk/floating-ips-bulk-delete-resp.xml.tpl b/nova/tests/integrated/api_samples/os-floating-ips-bulk/floating-ips-bulk-delete-resp.xml.tpl new file mode 100644 index 000000000000..3d77af334a56 --- /dev/null +++ b/nova/tests/integrated/api_samples/os-floating-ips-bulk/floating-ips-bulk-delete-resp.xml.tpl @@ -0,0 +1,2 @@ + +192.168.1.0/24 \ No newline at end of file diff --git a/nova/tests/integrated/api_samples/os-floating-ips-bulk/floating-ips-bulk-list-by-host-resp.json.tpl b/nova/tests/integrated/api_samples/os-floating-ips-bulk/floating-ips-bulk-list-by-host-resp.json.tpl new file mode 100644 index 000000000000..0eaaf75ae098 --- /dev/null +++ b/nova/tests/integrated/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/api_samples/os-floating-ips-bulk/floating-ips-bulk-list-by-host-resp.xml.tpl b/nova/tests/integrated/api_samples/os-floating-ips-bulk/floating-ips-bulk-list-by-host-resp.xml.tpl new file mode 100644 index 000000000000..4c3c8cd9cae2 --- /dev/null +++ b/nova/tests/integrated/api_samples/os-floating-ips-bulk/floating-ips-bulk-list-by-host-resp.xml.tpl @@ -0,0 +1,10 @@ + + + + eth0 + None + None + nova +
10.10.10.3
+
+
\ No newline at end of file diff --git a/nova/tests/integrated/api_samples/os-floating-ips-bulk/floating-ips-bulk-list-resp.json.tpl b/nova/tests/integrated/api_samples/os-floating-ips-bulk/floating-ips-bulk-list-resp.json.tpl new file mode 100644 index 000000000000..de1e622bb163 --- /dev/null +++ b/nova/tests/integrated/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/api_samples/os-floating-ips-bulk/floating-ips-bulk-list-resp.xml.tpl b/nova/tests/integrated/api_samples/os-floating-ips-bulk/floating-ips-bulk-list-resp.xml.tpl new file mode 100644 index 000000000000..6ef85bd87411 --- /dev/null +++ b/nova/tests/integrated/api_samples/os-floating-ips-bulk/floating-ips-bulk-list-resp.xml.tpl @@ -0,0 +1,24 @@ + + + + eth0 + None + None + nova +
10.10.10.1
+
+ + eth0 + None + None + nova +
10.10.10.2
+
+ + eth0 + None + None + nova +
10.10.10.3
+
+
\ No newline at end of file diff --git a/nova/tests/integrated/test_api_samples.py b/nova/tests/integrated/test_api_samples.py index 3a8488cd2c5f..e86c334b1e9a 100644 --- a/nova/tests/integrated/test_api_samples.py +++ b/nova/tests/integrated/test_api_samples.py @@ -944,6 +944,80 @@ class FloatingIpsXmlTest(FloatingIpsJsonTest): ctype = 'xml' +class FloatingIpsBulkJsonTest(ApiSampleTestBase): + extension_name = "nova.api.openstack.compute.contrib." \ + "floating_ips_bulk.Floating_ips_bulk" + + def setUp(self): + super(FloatingIpsBulkJsonTest, 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) + + def tearDown(self): + self.compute.db.floating_ip_bulk_destroy( + context.get_admin_context(), self.ip_pool) + super(FloatingIpsBulkJsonTest, self).tearDown() + + def test_floating_ips_bulk_list(self): + response = self._do_get('os-floating-ips-bulk') + self.assertEqual(response.status, 200) + subs = self._get_regexes() + return self._verify_response('floating-ips-bulk-list-resp', subs, + response) + + def test_floating_ips_bulk_list_by_host(self): + response = self._do_get('os-floating-ips-bulk/testHost') + self.assertEqual(response.status, 200) + subs = self._get_regexes() + return self._verify_response('floating-ips-bulk-list-by-host-resp', + subs, response) + + 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}) + self.assertEqual(response.status, 200) + subs = self._get_regexes() + return self._verify_response('floating-ips-bulk-create-resp', subs, + response) + + 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"}) + self.assertEqual(response.status, 200) + subs = self._get_regexes() + return self._verify_response('floating-ips-bulk-delete-resp', subs, + response) + + +class FloatingIpsBulkXmlTest(FloatingIpsBulkJsonTest): + ctype = 'xml' + + class KeyPairsSampleJsonTest(ApiSampleTestBase): extension_name = "nova.api.openstack.compute.contrib.keypairs.Keypairs" diff --git a/nova/tests/policy.json b/nova/tests/policy.json index 33a08c7c051c..20bfa3270613 100644 --- a/nova/tests/policy.json +++ b/nova/tests/policy.json @@ -106,6 +106,7 @@ "compute_extension:floating_ip_dns": "", "compute_extension:floating_ip_pools": "", "compute_extension:floating_ips": "", + "compute_extension:floating_ips_bulk": "", "compute_extension:fping": "", "compute_extension:fping:all_tenants": "is_admin:True", "compute_extension:hosts": "",