diff options
| author | Armando Migliaccio <armando.migliaccio@eu.citrix.com> | 2012-01-17 18:45:53 +0000 |
|---|---|---|
| committer | Armando Migliaccio <armando.migliaccio@eu.citrix.com> | 2012-01-25 18:33:18 +0000 |
| commit | f84a08528a5a604dbbff7e4ae0bdcd0e4e3fc19d (patch) | |
| tree | 8f6a5174908af5f6d9cd105d26c44e5fa2704dad /nova/api | |
| parent | 0a617713b881780bed67902833e1b971c9179042 (diff) | |
| download | nova-f84a08528a5a604dbbff7e4ae0bdcd0e4e3fc19d.tar.gz nova-f84a08528a5a604dbbff7e4ae0bdcd0e4e3fc19d.tar.xz nova-f84a08528a5a604dbbff7e4ae0bdcd0e4e3fc19d.zip | |
blueprint host-aggregates: OSAPI extensions
This commit introduces the OSAPI admin extensions for host aggregates.
This is part of a series of commits that have started with change:
https://review.openstack.org/#change,3035
Change-Id: If0c92dca7d6f5d794f84bdb2adc172c55dec6e74
Diffstat (limited to 'nova/api')
| -rw-r--r-- | nova/api/openstack/compute/contrib/aggregates.py | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/nova/api/openstack/compute/contrib/aggregates.py b/nova/api/openstack/compute/contrib/aggregates.py new file mode 100644 index 000000000..c0b0001e6 --- /dev/null +++ b/nova/api/openstack/compute/contrib/aggregates.py @@ -0,0 +1,223 @@ +# Copyright (c) 2012 Citrix Systems, Inc. +# 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. + +"""The Aggregate admin API extension.""" + +from webob import exc + +from nova.api.openstack import extensions +from nova import compute +from nova import exception +from nova import log as logging + + +LOG = logging.getLogger("nova.api.openstack.compute.contrib.host_aggregates") +authorize = extensions.extension_authorizer('compute', 'aggregates') + + +def _get_context(req): + return req.environ['nova.context'] + + +def get_host_from_body(fn): + """Makes sure that the host exists.""" + def wrapped(self, req, id, body, *args, **kwargs): + if len(body) == 1 and "host" in body: + host = body['host'] + else: + raise exc.HTTPBadRequest + return fn(self, req, id, host, *args, **kwargs) + return wrapped + + +class AggregateController(object): + """The Host Aggregates API controller for the OpenStack API.""" + def __init__(self): + self.api = compute.AggregateAPI() + + def index(self, req): + """Returns a list a host aggregate's id, name, availability_zone.""" + context = _get_context(req) + authorize(context) + aggregates = self.api.get_aggregate_list(context) + return {'aggregates': aggregates} + + def create(self, req, body): + """Creates an aggregate, given its name and availablity_zone.""" + context = _get_context(req) + authorize(context) + + if len(body) != 1: + raise exc.HTTPBadRequest + try: + host_aggregate = body["aggregate"] + aggregate_name = host_aggregate["name"] + availability_zone = host_aggregate["availability_zone"] + except KeyError: + raise exc.HTTPBadRequest + if len(host_aggregate) != 2: + raise exc.HTTPBadRequest + + try: + aggregate = self.api.create_aggregate(context, aggregate_name, + availability_zone) + except exception.AggregateNameExists: + raise exc.HTTPConflict + return self._marshall_aggregate(aggregate) + + def show(self, req, id): + """Shows the details of an aggregate, hosts and metadata included.""" + context = _get_context(req) + authorize(context) + try: + aggregate = self.api.get_aggregate(context, id) + except exception.AggregateNotFound: + raise exc.HTTPNotFound + return self._marshall_aggregate(aggregate) + + def update(self, req, id, body): + """Updates the name and/or availbility_zone of given aggregate.""" + context = _get_context(req) + authorize(context) + aggregate = id + + if len(body) != 1: + raise exc.HTTPBadRequest + try: + updates = body["aggregate"] + except KeyError: + raise exc.HTTPBadRequest + + if len(updates) < 1: + raise exc.HTTPBadRequest + + for key in updates.keys(): + if not key in ["name", "availability_zone"]: + raise exc.HTTPBadRequest + + try: + aggregate = self.api.update_aggregate(context, aggregate, updates) + except exception.AggregateNotFound: + raise exc.HTTPNotFound + + return self._marshall_aggregate(aggregate) + + def delete(self, req, id): + """Removes an aggregate by id.""" + context = _get_context(req) + authorize(context) + aggregate_id = id + try: + self.api.delete_aggregate(context, aggregate_id) + except exception.AggregateNotFound: + raise exc.HTTPNotFound + + def action(self, req, id, body): + _actions = { + 'add_host': self._add_host, + 'remove_host': self._remove_host, + 'set_metadata': self._set_metadata, + } + for action, data in body.iteritems(): + try: + return _actions[action](req, id, data) + except KeyError: + msg = _("Aggregates does not have %s action") % action + raise exc.HTTPBadRequest(explanation=msg) + + raise exc.HTTPBadRequest(explanation=_("Invalid request body")) + + @get_host_from_body + def _add_host(self, req, id, host): + """Adds a host to the specified aggregate.""" + context = _get_context(req) + authorize(context) + aggregate = id + try: + aggregate = self.api.add_host_to_aggregate(context, + aggregate, host) + except exception.AggregateNotFound: + raise exc.HTTPNotFound + except exception.ComputeHostNotFound: + raise exc.HTTPNotFound + except exception.AggregateHostConflict: + raise exc.HTTPConflict + except exception.AggregateHostExists: + raise exc.HTTPConflict + except exception.InvalidAggregateAction: + raise exc.HTTPConflict + return self._marshall_aggregate(aggregate) + + @get_host_from_body + def _remove_host(self, req, id, host): + """Removes a host from the specified aggregate.""" + context = _get_context(req) + authorize(context) + aggregate = id + try: + aggregate = self.api.remove_host_from_aggregate(context, + aggregate, host) + except exception.AggregateNotFound: + raise exc.HTTPNotFound + except exception.AggregateHostNotFound: + raise exc.HTTPNotFound + except exception.InvalidAggregateAction: + raise exc.HTTPConflict + return self._marshall_aggregate(aggregate) + + def _set_metadata(self, req, id, body): + """Replaces the aggregate's existing metadata with new metadata.""" + context = _get_context(req) + authorize(context) + aggregate = id + + if len(body) != 1: + raise exc.HTTPBadRequest + + try: + metadata = body["metadata"] + except KeyError: + raise exc.HTTPBadRequest + + try: + aggregate = self.api.update_aggregate_metadata(context, + aggregate, metadata) + except exception.AggregateNotFound: + raise exc.HTTPNotFound + + return self._marshall_aggregate(aggregate) + + def _marshall_aggregate(self, aggregate): + return {"aggregate": aggregate} + + +class Aggregates(extensions.ExtensionDescriptor): + """Admin-only aggregate administration""" + + name = "Aggregates" + alias = "os-aggregates" + namespace = "http://docs.openstack.org/compute/ext/aggregates/api/v1.1" + updated = "2012-01-12T00:00:00+00:00" + + def __init__(self, ext_mgr): + ext_mgr.register(self) + + def get_resources(self): + resources = [] + res = extensions.ResourceExtension('os-aggregates', + AggregateController(), + member_actions={"action": "POST", }) + resources.append(res) + return resources |
