summaryrefslogtreecommitdiffstats
path: root/nova/api
diff options
context:
space:
mode:
authorKravchenko Pavel <kpavel@il.ibm.com>2013-02-07 14:38:02 +0200
committerKravchenko Pavel <kpavel@il.ibm.com>2013-02-07 14:38:38 +0200
commit01a25e9890b957aef307b1bda22603f72cac12bf (patch)
tree17a8e1f1b30fbfb1b087b8f80ae75f8f21b4c639 /nova/api
parentfe16fded3d4ecfe71d7d0d0d4adbbb8d3cc0da48 (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.py98
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]