diff options
| author | Kravchenko Pavel <kpavel@il.ibm.com> | 2013-02-07 14:38:02 +0200 |
|---|---|---|
| committer | Kravchenko Pavel <kpavel@il.ibm.com> | 2013-02-07 14:38:38 +0200 |
| commit | 01a25e9890b957aef307b1bda22603f72cac12bf (patch) | |
| tree | 17a8e1f1b30fbfb1b087b8f80ae75f8f21b4c639 /nova/api | |
| parent | fe16fded3d4ecfe71d7d0d0d4adbbb8d3cc0da48 (diff) | |
Extension for rebuild-for-ha
Adds an extension for blueprint rebuild-for-ha
Evacuation of VM from a failed host for HA.
New api supports recreate/rebuild modes. With shared storage,
VM is recreated on the target from disk.
Otherwise, rebuild from original image is performed.
DocImpact
Change-Id: Id7e3e68dbaaf74e9314440d98195a92454078fd9
Co-authored-by: Oshrit Feder <oshritf@il.ibm.com>
Diffstat (limited to 'nova/api')
| -rw-r--r-- | nova/api/openstack/compute/contrib/evacuate.py | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/nova/api/openstack/compute/contrib/evacuate.py b/nova/api/openstack/compute/contrib/evacuate.py new file mode 100644 index 000000000..4c9229d1e --- /dev/null +++ b/nova/api/openstack/compute/contrib/evacuate.py @@ -0,0 +1,98 @@ +# Copyright 2013 OpenStack, LLC. +# +# 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. + + +from webob import exc + +from nova.api.openstack import common +from nova.api.openstack import extensions +from nova.api.openstack import wsgi +from nova import compute +from nova import exception +from nova.openstack.common import log as logging +from nova import utils + +LOG = logging.getLogger(__name__) +authorize = extensions.extension_authorizer('compute', 'evacuate') + + +class Controller(wsgi.Controller): + def __init__(self, *args, **kwargs): + super(Controller, self).__init__(*args, **kwargs) + self.compute_api = compute.API() + + @wsgi.action('evacuate') + def _evacuate(self, req, id, body): + """ + Permit admins to evacuate a server from a failed host + to a new one. + """ + context = req.environ["nova.context"] + if not context.is_admin: + msg = _("Instance evacuate is admin only functionality") + raise exc.HTTPForbidden(explanation=msg) + authorize(context) + + try: + if len(body) != 1: + raise exc.HTTPBadRequest(_("Malformed request body")) + + evacuate_body = body["evacuate"] + host = evacuate_body["host"] + on_shared_storage = utils.bool_from_str( + evacuate_body["onSharedStorage"]) + + if 'adminPass' in evacuate_body: + # check that if requested to evacuate server on shared storage + # password not specified + if on_shared_storage: + msg = _("admin password can't be changed on existing disk") + raise exc.HTTPBadRequest(explanation=msg) + + password = evacuate_body['adminPass'] + elif not on_shared_storage: + password = utils.generate_password() + + except (TypeError, KeyError): + msg = _("host and onSharedStorage must be specified.") + raise exc.HTTPBadRequest(explanation=msg) + + try: + instance = self.compute_api.get(context, id) + self.compute_api.evacuate(context, instance, host, + on_shared_storage, password) + except exception.InstanceInvalidState as state_error: + common.raise_http_conflict_for_instance_invalid_state(state_error, + 'evacuate') + except Exception as e: + msg = _("Error in evacuate, %s") % e + LOG.exception(msg, instance=instance) + raise exc.HTTPBadRequest(explanation=msg) + + if password: + return {'adminPass': password} + + +class Evacuate(extensions.ExtensionDescriptor): + """Enables server evacuation.""" + + name = "Evacuate" + alias = "os-evacuate" + namespace = "http://docs.openstack.org/compute/ext/evacuate/api/v2" + updated = "2013-01-06T00:00:00+00:00" + + def get_controller_extensions(self): + controller = Controller() + extension = extensions.ControllerExtension(self, 'servers', controller) + return [extension] |
