From 37d42caeab3a9e040291afecb5238b28028f566e Mon Sep 17 00:00:00 2001 From: Chris Yeoh Date: Mon, 17 Dec 2012 10:40:06 +1030 Subject: Add more association support to network API Adds API support to: - Disassociate only host from network - Disassociate only project from network - Associate network with host (project already supported) New functionality is added to a new extension networks_associate, but the original networks extension is modified to allow networks_associate to extend how it needs to. The original behavior of the networks extension is preserved (no new functionality, nor change in existing behavior) in terms of the API presented. Bumps RPC API version for network RPC server version in order add the associate function which allows to both associate and disassociate a network with a host and or tenant. Has overlap with disassociate and add_network_to_project but these are kept for backwards compatibility DocImpact Implmenents: blueprint apis-for-nova-manage Change-Id: I78fd76e0696d1c872646355ab04d32f051551def --- nova/api/openstack/compute/contrib/networks.py | 40 +++++-------- .../compute/contrib/networks_associate.py | 69 ++++++++++++++++++++++ 2 files changed, 84 insertions(+), 25 deletions(-) create mode 100644 nova/api/openstack/compute/contrib/networks_associate.py (limited to 'nova/api') diff --git a/nova/api/openstack/compute/contrib/networks.py b/nova/api/openstack/compute/contrib/networks.py index 0a494ea88..a45de72fe 100644 --- a/nova/api/openstack/compute/contrib/networks.py +++ b/nova/api/openstack/compute/contrib/networks.py @@ -21,6 +21,8 @@ import webob from webob import exc from nova.api.openstack import extensions +from nova.api.openstack import wsgi +from nova import db from nova import exception from nova import network from nova.openstack.common import log as logging @@ -52,35 +54,11 @@ def network_dict(context, network): return {} -class NetworkController(object): +class NetworkController(wsgi.Controller): def __init__(self, network_api=None): self.network_api = network_api or network.API() - def action(self, req, id, body): - _actions = { - 'disassociate': self._disassociate, - } - - for action, data in body.iteritems(): - try: - return _actions[action](req, id, body) - except KeyError: - msg = _("Network does not have %s action") % action - raise exc.HTTPBadRequest(explanation=msg) - - raise exc.HTTPBadRequest(explanation=_("Invalid request body")) - - def _disassociate(self, request, network_id, body): - context = request.environ['nova.context'] - authorize(context) - LOG.debug(_("Disassociating network with id %s"), network_id) - try: - self.network_api.disassociate(context, network_id) - except exception.NetworkNotFound: - raise exc.HTTPNotFound(_("Network not found")) - return exc.HTTPAccepted() - def index(self, req): context = req.environ['nova.context'] authorize_view(context) @@ -88,6 +66,18 @@ class NetworkController(object): result = [network_dict(context, net_ref) for net_ref in networks] return {'networks': result} + @wsgi.action("disassociate") + def _disassociate_host_and_project(self, req, id, body): + context = req.environ['nova.context'] + authorize(context) + LOG.debug(_("Disassociating network with id %s"), id) + + try: + self.network_api.associate(context, id, host=None, project=None) + except exception.NetworkNotFound: + raise exc.HTTPNotFound(_("Network not found")) + return exc.HTTPAccepted() + def show(self, req, id): context = req.environ['nova.context'] authorize_view(context) diff --git a/nova/api/openstack/compute/contrib/networks_associate.py b/nova/api/openstack/compute/contrib/networks_associate.py new file mode 100644 index 000000000..a923c769d --- /dev/null +++ b/nova/api/openstack/compute/contrib/networks_associate.py @@ -0,0 +1,69 @@ +import netaddr +import webob +from webob import exc + +from nova.api.openstack import extensions +from nova.api.openstack import wsgi +from nova import exception +from nova import network +from nova.openstack.common import log as logging + +LOG = logging.getLogger(__name__) +authorize = extensions.extension_authorizer('compute', 'networks_associate') + + +class NetworkAssociateActionController(wsgi.Controller): + """Network Association API Controller.""" + + def __init__(self, network_api=None): + self.network_api = network_api or network.API() + + @wsgi.action("disassociate_host") + def _disassociate_host_only(self, req, id, body): + context = req.environ['nova.context'] + authorize(context) + LOG.debug(_("Disassociating host with network with id %s"), id) + try: + self.network_api.associate(context, id, host=None) + except exception.NetworkNotFound: + raise exc.HTTPNotFound(_("Network not found")) + return exc.HTTPAccepted() + + @wsgi.action("disassociate_project") + def _disassociate_project_only(self, req, id, body): + context = req.environ['nova.context'] + authorize(context) + LOG.debug(_("Disassociating project with network with id %s"), id) + try: + self.network_api.associate(context, id, project=None) + except exception.NetworkNotFound: + raise exc.HTTPNotFound(_("Network not found")) + return exc.HTTPAccepted() + + @wsgi.action("associate_host") + def _associate_host(self, req, id, body): + context = req.environ['nova.context'] + authorize(context) + + try: + self.network_api.associate(context, id, + host=body['associate_host']) + except exception.NetworkNotFound: + raise exc.HTTPNotFound(_("Network not found")) + return exc.HTTPAccepted() + + +class Networks_associate(extensions.ExtensionDescriptor): + """Network association support""" + + name = "NetworkAssociationSupport" + alias = "os-networks-associate" + namespace = ("http://docs.openstack.org/compute/ext/" + "networks_associate/api/v2") + updated = "2012-11-19T00:00:00+00:00" + + def get_controller_extensions(self): + extension = extensions.ControllerExtension( + self, 'os-networks', NetworkAssociateActionController()) + + return [extension] -- cgit