summaryrefslogtreecommitdiffstats
path: root/nova/api
diff options
context:
space:
mode:
authorSandy Walsh <sandy@sandywalsh.com>2012-01-30 13:10:50 -0800
committerChris Behrens <cbehrens@codestud.com>2012-02-16 17:53:00 +0000
commit26227b79e9246a87eeb83766cfcc8e96d294d28b (patch)
treecba29636bf65611a2816acfd455b503d79c43309 /nova/api
parentf5e17bbc155203feb8bba4f34ed93d22b1b8e95b (diff)
Removed zones from api and distributed scheduler
There is a new Zones implementation coming that will use AMQP-to-AMQP channels vs. the public API. This is being done for three reasons: 1. remove complications in the OpenStack API (and possibly allow EC2 Zones) 2. remove dependencies on keystone and novaclient 3. faster scheduling (fewer chances for race conditions) Learn more here: http://wiki.openstack.org/EssexSchedulerImprovements Change-Id: I6fe538923dd5ae19276afac2ac3311a285fd5c99
Diffstat (limited to 'nova/api')
-rw-r--r--nova/api/openstack/compute/contrib/admin_actions.py20
-rw-r--r--nova/api/openstack/compute/contrib/console_output.py2
-rw-r--r--nova/api/openstack/compute/contrib/consoles.py2
-rw-r--r--nova/api/openstack/compute/contrib/disk_config.py6
-rw-r--r--nova/api/openstack/compute/contrib/extended_status.py2
-rw-r--r--nova/api/openstack/compute/contrib/server_diagnostics.py3
-rw-r--r--nova/api/openstack/compute/contrib/zones.py228
-rw-r--r--nova/api/openstack/compute/servers.py58
8 files changed, 14 insertions, 307 deletions
diff --git a/nova/api/openstack/compute/contrib/admin_actions.py b/nova/api/openstack/compute/contrib/admin_actions.py
index 69340648b..b1bfaf6ac 100644
--- a/nova/api/openstack/compute/contrib/admin_actions.py
+++ b/nova/api/openstack/compute/contrib/admin_actions.py
@@ -45,8 +45,6 @@ class AdminActionsController(wsgi.Controller):
# TODO(bcwaldon): These action names should be prefixed with 'os-'
@wsgi.action('pause')
- @exception.novaclient_converter
- @scheduler_api.redirect_handler
def _pause(self, req, id, body):
"""Permit Admins to pause the server"""
ctxt = req.environ['nova.context']
@@ -64,8 +62,6 @@ class AdminActionsController(wsgi.Controller):
return webob.Response(status_int=202)
@wsgi.action('unpause')
- @exception.novaclient_converter
- @scheduler_api.redirect_handler
def _unpause(self, req, id, body):
"""Permit Admins to unpause the server"""
ctxt = req.environ['nova.context']
@@ -83,8 +79,6 @@ class AdminActionsController(wsgi.Controller):
return webob.Response(status_int=202)
@wsgi.action('suspend')
- @exception.novaclient_converter
- @scheduler_api.redirect_handler
def _suspend(self, req, id, body):
"""Permit admins to suspend the server"""
context = req.environ['nova.context']
@@ -102,8 +96,6 @@ class AdminActionsController(wsgi.Controller):
return webob.Response(status_int=202)
@wsgi.action('resume')
- @exception.novaclient_converter
- @scheduler_api.redirect_handler
def _resume(self, req, id, body):
"""Permit admins to resume the server from suspend"""
context = req.environ['nova.context']
@@ -121,8 +113,6 @@ class AdminActionsController(wsgi.Controller):
return webob.Response(status_int=202)
@wsgi.action('migrate')
- @exception.novaclient_converter
- @scheduler_api.redirect_handler
def _migrate(self, req, id, body):
"""Permit admins to migrate a server to a new host"""
context = req.environ['nova.context']
@@ -139,8 +129,6 @@ class AdminActionsController(wsgi.Controller):
return webob.Response(status_int=202)
@wsgi.action('resetNetwork')
- @exception.novaclient_converter
- @scheduler_api.redirect_handler
def _reset_network(self, req, id, body):
"""Permit admins to reset networking on an server"""
context = req.environ['nova.context']
@@ -155,8 +143,6 @@ class AdminActionsController(wsgi.Controller):
return webob.Response(status_int=202)
@wsgi.action('injectNetworkInfo')
- @exception.novaclient_converter
- @scheduler_api.redirect_handler
def _inject_network_info(self, req, id, body):
"""Permit admins to inject network info into a server"""
context = req.environ['nova.context']
@@ -173,8 +159,6 @@ class AdminActionsController(wsgi.Controller):
return webob.Response(status_int=202)
@wsgi.action('lock')
- @exception.novaclient_converter
- @scheduler_api.redirect_handler
def _lock(self, req, id, body):
"""Permit admins to lock a server"""
context = req.environ['nova.context']
@@ -191,8 +175,6 @@ class AdminActionsController(wsgi.Controller):
return webob.Response(status_int=202)
@wsgi.action('unlock')
- @exception.novaclient_converter
- @scheduler_api.redirect_handler
def _unlock(self, req, id, body):
"""Permit admins to lock a server"""
context = req.environ['nova.context']
@@ -277,8 +259,6 @@ class AdminActionsController(wsgi.Controller):
return resp
@wsgi.action('os-migrateLive')
- @exception.novaclient_converter
- @scheduler_api.redirect_handler
def _migrate_live(self, req, id, body):
"""Permit admins to (live) migrate a server to a new host"""
context = req.environ["nova.context"]
diff --git a/nova/api/openstack/compute/contrib/console_output.py b/nova/api/openstack/compute/contrib/console_output.py
index 0752c3c70..6fc7fcbf0 100644
--- a/nova/api/openstack/compute/contrib/console_output.py
+++ b/nova/api/openstack/compute/contrib/console_output.py
@@ -41,7 +41,7 @@ class ConsoleOutputController(wsgi.Controller):
authorize(context)
try:
- instance = self.compute_api.routing_get(context, id)
+ instance = self.compute_api.get(context, id)
except exception.NotFound:
raise webob.exc.HTTPNotFound(_('Instance not found'))
diff --git a/nova/api/openstack/compute/contrib/consoles.py b/nova/api/openstack/compute/contrib/consoles.py
index f308c6717..833eb0f39 100644
--- a/nova/api/openstack/compute/contrib/consoles.py
+++ b/nova/api/openstack/compute/contrib/consoles.py
@@ -44,7 +44,7 @@ class ConsolesController(wsgi.Controller):
raise webob.exc.HTTPBadRequest(_('Missing type specification'))
try:
- instance = self.compute_api.routing_get(context, id)
+ instance = self.compute_api.get(context, id)
except exception.NotFound:
raise webob.exc.HTTPNotFound(_('Instance not found'))
diff --git a/nova/api/openstack/compute/contrib/disk_config.py b/nova/api/openstack/compute/contrib/disk_config.py
index 5b249478a..e338fa5ee 100644
--- a/nova/api/openstack/compute/contrib/disk_config.py
+++ b/nova/api/openstack/compute/contrib/disk_config.py
@@ -103,12 +103,6 @@ class ServersDiskConfigTemplate(xmlutil.TemplateBuilder):
class ServerDiskConfigController(wsgi.Controller):
def _add_disk_config(self, context, servers):
- # Filter out any servers that already have the key set
- # (most likely from a remote zone)
- servers = [s for s in servers if API_DISK_CONFIG not in s]
- if not servers:
- return
-
# Get DB information for servers
uuids = [server['id'] for server in servers]
db_servers = db.instance_get_all_by_filters(context,
diff --git a/nova/api/openstack/compute/contrib/extended_status.py b/nova/api/openstack/compute/contrib/extended_status.py
index 9447bf300..88a5f12a4 100644
--- a/nova/api/openstack/compute/contrib/extended_status.py
+++ b/nova/api/openstack/compute/contrib/extended_status.py
@@ -56,7 +56,7 @@ class ExtendedStatusController(wsgi.Controller):
resp_obj.attach(xml=ExtendedStatusTemplate())
try:
- instance = self.compute_api.routing_get(context, id)
+ instance = self.compute_api.get(context, id)
except exception.NotFound:
explanation = _("Server not found.")
raise exc.HTTPNotFound(explanation=explanation)
diff --git a/nova/api/openstack/compute/contrib/server_diagnostics.py b/nova/api/openstack/compute/contrib/server_diagnostics.py
index 49afcac01..c03cd2d47 100644
--- a/nova/api/openstack/compute/contrib/server_diagnostics.py
+++ b/nova/api/openstack/compute/contrib/server_diagnostics.py
@@ -20,7 +20,6 @@ from nova.api.openstack import wsgi
from nova.api.openstack import xmlutil
from nova import compute
from nova import exception
-from nova.scheduler import api as scheduler_api
authorize = extensions.extension_authorizer('compute', 'server_diagnostics')
@@ -38,8 +37,6 @@ class ServerDiagnosticsTemplate(xmlutil.TemplateBuilder):
class ServerDiagnosticsController(object):
@wsgi.serializers(xml=ServerDiagnosticsTemplate)
- @exception.novaclient_converter
- @scheduler_api.redirect_handler
def index(self, req, server_id):
context = req.environ["nova.context"]
authorize(context)
diff --git a/nova/api/openstack/compute/contrib/zones.py b/nova/api/openstack/compute/contrib/zones.py
deleted file mode 100644
index 8db16f235..000000000
--- a/nova/api/openstack/compute/contrib/zones.py
+++ /dev/null
@@ -1,228 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright 2011 OpenStack LLC.
-# 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 zones extension."""
-
-import json
-
-from nova.api.openstack import common
-from nova.api.openstack.compute import servers
-from nova.api.openstack import extensions
-from nova.api.openstack import xmlutil
-from nova.api.openstack import wsgi
-from nova.compute import api as compute
-from nova import crypto
-from nova import exception
-from nova import flags
-from nova import log as logging
-import nova.scheduler.api
-
-
-LOG = logging.getLogger(__name__)
-FLAGS = flags.FLAGS
-authorize = extensions.extension_authorizer('compute', 'zones')
-
-
-class CapabilitySelector(object):
- def __call__(self, obj, do_raise=False):
- return [(k, v) for k, v in obj.items()
- if k not in ('id', 'api_url', 'name', 'capabilities')]
-
-
-def make_zone(elem):
- elem.set('id')
- elem.set('api_url')
- elem.set('name')
- elem.set('capabilities')
-
- cap = xmlutil.SubTemplateElement(elem, xmlutil.Selector(0),
- selector=CapabilitySelector())
- cap.text = 1
-
-
-zone_nsmap = {None: wsgi.XMLNS_V10}
-
-
-class ZoneTemplate(xmlutil.TemplateBuilder):
- def construct(self):
- root = xmlutil.TemplateElement('zone', selector='zone')
- make_zone(root)
- return xmlutil.MasterTemplate(root, 1, nsmap=zone_nsmap)
-
-
-class ZonesTemplate(xmlutil.TemplateBuilder):
- def construct(self):
- root = xmlutil.TemplateElement('zones')
- elem = xmlutil.SubTemplateElement(root, 'zone', selector='zones')
- make_zone(elem)
- return xmlutil.MasterTemplate(root, 1, nsmap=zone_nsmap)
-
-
-class WeightsTemplate(xmlutil.TemplateBuilder):
- def construct(self):
- root = xmlutil.TemplateElement('weights')
- weight = xmlutil.SubTemplateElement(root, 'weight', selector='weights')
- blob = xmlutil.SubTemplateElement(weight, 'blob')
- blob.text = 'blob'
- inner_weight = xmlutil.SubTemplateElement(weight, 'weight')
- inner_weight.text = 'weight'
- return xmlutil.MasterTemplate(root, 1, nsmap=zone_nsmap)
-
-
-def _filter_keys(item, keys):
- """
- Filters all model attributes except for keys
- item is a dict
-
- """
- return dict((k, v) for k, v in item.iteritems() if k in keys)
-
-
-def _exclude_keys(item, keys):
- return dict((k, v) for k, v in item.iteritems() if k and (k not in keys))
-
-
-def _scrub_zone(zone):
- return _exclude_keys(zone, ('username', 'password', 'created_at',
- 'deleted', 'deleted_at', 'updated_at'))
-
-
-def check_encryption_key(func):
- def wrapped(*args, **kwargs):
- if not FLAGS.build_plan_encryption_key:
- raise exception.Error(_("--build_plan_encryption_key not set"))
- return func(*args, **kwargs)
- return wrapped
-
-
-class Controller(object):
- """Controller for Zone resources."""
-
- def __init__(self):
- self.compute_api = compute.API()
-
- @wsgi.serializers(xml=ZonesTemplate)
- def index(self, req):
- """Return all zones in brief"""
- authorize(req.environ['nova.context'])
- # Ask the ZoneManager in the Scheduler for most recent data,
- # or fall-back to the database ...
- items = nova.scheduler.api.get_zone_list(req.environ['nova.context'])
- items = common.limited(items, req)
- items = [_scrub_zone(item) for item in items]
- return dict(zones=items)
-
- @wsgi.serializers(xml=ZonesTemplate)
- def detail(self, req):
- """Return all zones in detail"""
- return self.index(req)
-
- @wsgi.serializers(xml=ZoneTemplate)
- def info(self, req):
- """Return name and capabilities for this zone."""
- context = req.environ['nova.context']
- authorize(context)
- zone_capabs = nova.scheduler.api.get_zone_capabilities(context)
- # NOTE(comstud): This should probably return, instead:
- # {'zone': {'name': FLAGS.zone_name,
- # 'capabilities': zone_capabs}}
- zone_capabs['name'] = FLAGS.zone_name
- return dict(zone=zone_capabs)
-
- @wsgi.serializers(xml=ZoneTemplate)
- def show(self, req, id):
- """Return data about the given zone id"""
- context = req.environ['nova.context']
- authorize(context)
- zone_id = int(id)
- zone = nova.scheduler.api.zone_get(context, zone_id)
- return dict(zone=_scrub_zone(zone))
-
- def delete(self, req, id):
- """Delete a child zone entry."""
- authorize(req.environ['nova.context'])
- zone_id = int(id)
- nova.scheduler.api.zone_delete(req.environ['nova.context'], zone_id)
- return {}
-
- @wsgi.serializers(xml=ZoneTemplate)
- @wsgi.deserializers(xml=servers.CreateDeserializer)
- def create(self, req, body):
- """Create a child zone entry."""
- context = req.environ['nova.context']
- authorize(context)
- zone = nova.scheduler.api.zone_create(context, body["zone"])
- return dict(zone=_scrub_zone(zone))
-
- @wsgi.serializers(xml=ZoneTemplate)
- def update(self, req, id, body):
- """Update a child zone entry."""
- context = req.environ['nova.context']
- authorize(context)
- zone_id = int(id)
- zone = nova.scheduler.api.zone_update(context, zone_id, body["zone"])
- return dict(zone=_scrub_zone(zone))
-
- @wsgi.serializers(xml=WeightsTemplate)
- @check_encryption_key
- def select(self, req, body):
- """Returns a weighted list of costs to create instances
- of desired capabilities."""
- context = req.environ['nova.context']
- authorize(context)
- specs = json.loads(body)
- build_plan = nova.scheduler.api.select(context, specs=specs)
- cooked = self._scrub_build_plan(build_plan)
- return {"weights": cooked}
-
- def _scrub_build_plan(self, build_plan):
- """Remove all the confidential data and return a sanitized
- version of the build plan. Include an encrypted full version
- of the weighting entry so we can get back to it later."""
- encryptor = crypto.encryptor(FLAGS.build_plan_encryption_key)
- cooked = []
- for entry in build_plan:
- json_entry = json.dumps(entry)
- cipher_text = encryptor(json_entry)
- cooked.append(dict(weight=entry['weight'],
- blob=cipher_text))
- return cooked
-
-
-class Zones(extensions.ExtensionDescriptor):
- """Enables zones-related functionality such as adding child zones,
- listing child zones, getting the capabilities of the local zone,
- and returning build plans to parent zones' schedulers
- """
-
- name = "Zones"
- alias = "os-zones"
- namespace = "http://docs.openstack.org/compute/ext/zones/api/v1.1"
- updated = "2011-09-21T00:00:00+00:00"
-
- def get_resources(self):
- #NOTE(bcwaldon): This resource should be prefixed with 'os-'
- coll_actions = {
- 'detail': 'GET',
- 'info': 'GET',
- 'select': 'POST',
- }
-
- res = extensions.ResourceExtension('zones',
- Controller(),
- collection_actions=coll_actions)
- return [res]
diff --git a/nova/api/openstack/compute/servers.py b/nova/api/openstack/compute/servers.py
index 649566ec9..87e66b71f 100644
--- a/nova/api/openstack/compute/servers.py
+++ b/nova/api/openstack/compute/servers.py
@@ -33,7 +33,6 @@ from nova import exception
from nova import flags
from nova import log as logging
from nova.rpc import common as rpc_common
-from nova.scheduler import api as scheduler_api
from nova import utils
@@ -417,18 +416,14 @@ class Controller(wsgi.Controller):
remove_invalid_options(context, search_opts,
self._get_server_search_options())
- # Convert local_zone_only into a boolean
- search_opts['local_zone_only'] = utils.bool_from_str(
- search_opts.get('local_zone_only', False))
-
- # If search by 'status', we need to convert it to 'vm_state'
- # to pass on to child zones.
- if 'status' in search_opts:
- status = search_opts['status']
+ # Verify search by 'status' contains a valid status.
+ # Convert it to filter by vm_state for compute_api.
+ status = search_opts.pop('status', None)
+ if status is not None:
state = common.vm_state_from_status(status)
if state is None:
- reason = _('Invalid server status: %(status)s') % locals()
- raise exception.InvalidInput(reason=reason)
+ msg = _('Invalid server status: %(status)s') % locals()
+ raise exc.HTTPBadRequest(explanation=msg)
search_opts['vm_state'] = state
if 'changes-since' in search_opts:
@@ -474,7 +469,7 @@ class Controller(wsgi.Controller):
def _get_server(self, context, instance_uuid):
"""Utility function for looking up an instance by uuid"""
try:
- return self.compute_api.routing_get(context, instance_uuid)
+ return self.compute_api.get(context, instance_uuid)
except exception.NotFound:
raise exc.HTTPNotFound()
@@ -602,13 +597,11 @@ class Controller(wsgi.Controller):
raise exc.HTTPBadRequest(explanation=expl)
@wsgi.serializers(xml=ServerTemplate)
- @exception.novaclient_converter
- @scheduler_api.redirect_handler
def show(self, req, id):
""" Returns server details by server id """
try:
context = req.environ['nova.context']
- instance = self.compute_api.routing_get(context, id)
+ instance = self.compute_api.get(context, id)
self._add_instance_faults(context, [instance])
return self._view_builder.show(req, instance)
except exception.NotFound:
@@ -684,8 +677,6 @@ class Controller(wsgi.Controller):
msg = _("Invalid flavorRef provided.")
raise exc.HTTPBadRequest(explanation=msg)
- zone_blob = server_dict.get('blob')
-
# optional openstack extensions:
key_name = server_dict.get('key_name')
user_data = server_dict.get('user_data')
@@ -698,14 +689,6 @@ class Controller(wsgi.Controller):
block_device_mapping = self._get_block_device_mapping(server_dict)
- # Only allow admins to specify their own reservation_ids
- # This is really meant to allow zones to work.
- reservation_id = server_dict.get('reservation_id')
- if all([reservation_id is not None,
- reservation_id != '',
- not context.is_admin]):
- reservation_id = None
-
ret_resv_id = server_dict.get('return_reservation_id', False)
min_count = server_dict.get('min_count')
@@ -736,8 +719,6 @@ class Controller(wsgi.Controller):
access_ip_v6=access_ip_v6,
injected_files=injected_files,
admin_password=password,
- zone_blob=zone_blob,
- reservation_id=reservation_id,
min_count=min_count,
max_count=max_count,
requested_networks=requested_networks,
@@ -795,7 +776,6 @@ class Controller(wsgi.Controller):
self.compute_api.delete(context, instance)
@wsgi.serializers(xml=ServerTemplate)
- @scheduler_api.redirect_handler
def update(self, req, id, body):
"""Update server then pass on to version-specific controller"""
if len(req.body) == 0:
@@ -827,7 +807,7 @@ class Controller(wsgi.Controller):
body['server']['auto_disk_config'])
update_dict['auto_disk_config'] = auto_disk_config
- instance = self.compute_api.routing_get(ctxt, id)
+ instance = self.compute_api.get(ctxt, id)
try:
self.compute_api.update(ctxt, instance, **update_dict)
@@ -843,8 +823,6 @@ class Controller(wsgi.Controller):
@wsgi.serializers(xml=FullServerTemplate)
@wsgi.deserializers(xml=ActionDeserializer)
@wsgi.action('confirmResize')
- @exception.novaclient_converter
- @scheduler_api.redirect_handler
def _action_confirm_resize(self, req, id, body):
context = req.environ['nova.context']
instance = self._get_server(context, id)
@@ -865,8 +843,6 @@ class Controller(wsgi.Controller):
@wsgi.serializers(xml=FullServerTemplate)
@wsgi.deserializers(xml=ActionDeserializer)
@wsgi.action('revertResize')
- @exception.novaclient_converter
- @scheduler_api.redirect_handler
def _action_revert_resize(self, req, id, body):
context = req.environ['nova.context']
instance = self._get_server(context, id)
@@ -887,8 +863,6 @@ class Controller(wsgi.Controller):
@wsgi.serializers(xml=FullServerTemplate)
@wsgi.deserializers(xml=ActionDeserializer)
@wsgi.action('reboot')
- @exception.novaclient_converter
- @scheduler_api.redirect_handler
def _action_reboot(self, req, id, body):
if 'reboot' in body and 'type' in body['reboot']:
valid_reboot_types = ['HARD', 'SOFT']
@@ -935,8 +909,6 @@ class Controller(wsgi.Controller):
return webob.Response(status_int=202)
@wsgi.response(204)
- @exception.novaclient_converter
- @scheduler_api.redirect_handler
def delete(self, req, id):
""" Destroys a server """
try:
@@ -975,8 +947,6 @@ class Controller(wsgi.Controller):
@wsgi.serializers(xml=FullServerTemplate)
@wsgi.deserializers(xml=ActionDeserializer)
@wsgi.action('changePassword')
- @exception.novaclient_converter
- @scheduler_api.redirect_handler
def _action_change_password(self, req, id, body):
context = req.environ['nova.context']
if (not 'changePassword' in body
@@ -1007,8 +977,6 @@ class Controller(wsgi.Controller):
@wsgi.serializers(xml=FullServerTemplate)
@wsgi.deserializers(xml=ActionDeserializer)
@wsgi.action('resize')
- @exception.novaclient_converter
- @scheduler_api.redirect_handler
def _action_resize(self, req, id, body):
""" Resizes a given instance to the flavor size requested """
try:
@@ -1030,8 +998,6 @@ class Controller(wsgi.Controller):
@wsgi.serializers(xml=FullServerTemplate)
@wsgi.deserializers(xml=ActionDeserializer)
@wsgi.action('rebuild')
- @exception.novaclient_converter
- @scheduler_api.redirect_handler
def _action_rebuild(self, req, id, body):
"""Rebuild an instance with the given attributes"""
try:
@@ -1115,8 +1081,6 @@ class Controller(wsgi.Controller):
@wsgi.serializers(xml=FullServerTemplate)
@wsgi.deserializers(xml=ActionDeserializer)
@wsgi.action('createImage')
- @exception.novaclient_converter
- @scheduler_api.redirect_handler
@common.check_snapshots_enabled
def _action_create_image(self, req, id, body):
"""Snapshot a server instance."""
@@ -1173,8 +1137,8 @@ class Controller(wsgi.Controller):
def _get_server_search_options(self):
"""Return server search options allowed by non-admin"""
- return ('reservation_id', 'name', 'local_zone_only',
- 'status', 'image', 'flavor', 'changes-since')
+ return ('reservation_id', 'name', 'status', 'image', 'flavor',
+ 'changes-since')
def create_resource():