From 576ada198aa659fd6a0a50fe8ba1ce7d60633089 Mon Sep 17 00:00:00 2001 From: Chris Yeoh Date: Thu, 1 Nov 2012 10:49:53 +1030 Subject: Adds API for bulk creation/deletion of floating IPs This adds an extension that provides a REST API for the bulk creation, deletion and listing of floating IPs. The interface is accessed via /v2/{tenant_id}/os-floating-ips-bulk This forms part of the work to provide APIs for functionality currently implemented by nova-manage that needs direct db access so nova-manage can eventually be removed Implements: blueprint apis-for-nova-manage DocImpact Change-Id: I621e2b070a896f7230cdf3f26f78ded85e72cf16 --- .../openstack/compute/contrib/floating_ips_bulk.py | 176 +++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 nova/api/openstack/compute/contrib/floating_ips_bulk.py (limited to 'nova/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 000000000..59d9d24b6 --- /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 -- cgit