summaryrefslogtreecommitdiffstats
path: root/nova/api
diff options
context:
space:
mode:
authormasumotok <masumotok@nttdata.co.jp>2012-01-26 04:38:41 -0800
committermasumotok <masumotok@nttdata.co.jp>2012-01-26 04:38:41 -0800
commit09ccc2f9315eb0441d5f7793326614cc25814089 (patch)
tree5b8d0036919b9f35474b3802b54261077113883d /nova/api
parent6142230ccf2555650dbb902a5c342a342e9b2582 (diff)
Adding live migration server actions
Change-Id: I5e1f5dddaf45d1c6eae8666647425bff748b639e
Diffstat (limited to 'nova/api')
-rw-r--r--nova/api/openstack/compute/contrib/admin_actions.py37
-rw-r--r--nova/api/openstack/compute/contrib/hosts.py76
2 files changed, 113 insertions, 0 deletions
diff --git a/nova/api/openstack/compute/contrib/admin_actions.py b/nova/api/openstack/compute/contrib/admin_actions.py
index cbd54117d..f68126fb2 100644
--- a/nova/api/openstack/compute/contrib/admin_actions.py
+++ b/nova/api/openstack/compute/contrib/admin_actions.py
@@ -272,6 +272,43 @@ class AdminActionsController(wsgi.Controller):
resp.headers['Location'] = image_ref
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"]
+ # Expected to use AuthMiddleware.
+ # Otherwise, non-admin user can use live migration
+ if not context.is_admin:
+ msg = _("Live migration is admin only functionality")
+ raise exc.HTTPForbidden(explanation=msg)
+
+ try:
+ block_migration = body["os-migrateLive"]["block_migration"]
+ disk_over_commit = body["os-migrateLive"]["disk_over_commit"]
+ host = body["os-migrateLive"]["host"]
+ except (TypeError, KeyError):
+ msg = _("host and block_migration must be specified.")
+ raise exc.HTTPBadRequest(explanation=msg)
+
+ try:
+ instance = self.compute_api.get(context, id)
+ result = scheduler_api.live_migration(context,
+ block_migration,
+ disk_over_commit,
+ instance["id"],
+ host,
+ topic=FLAGS.compute_topic)
+ except Exception, e:
+ msg = _("Live migration of instance %(id)s to host %(host)s"
+ " failed") % locals()
+ LOG.exception(msg)
+ # Return messages from scheduler
+ raise exc.HTTPBadRequest(explanation=msg)
+
+ return webob.Response(status_int=202)
+
class Admin_actions(extensions.ExtensionDescriptor):
"""Enable admin-only server actions
diff --git a/nova/api/openstack/compute/contrib/hosts.py b/nova/api/openstack/compute/contrib/hosts.py
index b522e6a98..53f1a064a 100644
--- a/nova/api/openstack/compute/contrib/hosts.py
+++ b/nova/api/openstack/compute/contrib/hosts.py
@@ -23,6 +23,7 @@ from nova.api.openstack import wsgi
from nova.api.openstack import xmlutil
from nova.api.openstack import extensions
from nova import compute
+from nova import db
from nova import exception
from nova import flags
from nova import log as logging
@@ -82,6 +83,15 @@ class HostDeserializer(wsgi.XMLDeserializer):
return dict(body=updates)
+class HostShowTemplate(xmlutil.TemplateBuilder):
+ def construct(self):
+ root = xmlutil.TemplateElement('host', selector='host')
+ root.set('resource')
+ root.set('usage')
+
+ return xmlutil.MasterTemplate(root, 1)
+
+
def _list_hosts(req, service=None):
"""Returns a summary list of hosts, optionally filtering
by service type.
@@ -176,6 +186,72 @@ class HostController(object):
def reboot(self, req, id):
return self._host_power_action(req, host=id, action="reboot")
+ @wsgi.serializers(xml=HostShowTemplate)
+ def show(self, req, id):
+ """Shows the physical/usage resource given by hosts.
+
+ :param context: security context
+ :param host: hostname
+ :returns:
+ {'host': {'resource':D1, 'usage':{proj_id1:D2,..}}}
+
+ 'resource' shows "available" and "in-use" vcpus, memory and disk.
+ 'usage' shows "in-use" vcpus, memory and disk per project.
+
+ D1: {'vcpus': 16, 'memory_mb': 2048, 'local_gb': 2048,
+ 'vcpus_used': 12, 'memory_mb_used': 10240,
+ 'local_gb_used': 64}
+ D2: {'vcpus': 1, 'memory_mb': 2048, 'local_gb': 20}
+ """
+ host = id
+ context = req.environ['nova.context']
+ # Expected to use AuthMiddleware.
+ # Otherwise, non-admin user can use describe-resource
+ if not context.is_admin:
+ msg = _("Describe-resource is admin only functionality")
+ raise webob.exc.HTTPForbidden(explanation=msg)
+
+ # Getting compute node info and related instances info
+ try:
+ compute_ref = db.service_get_all_compute_by_host(context, host)
+ compute_ref = compute_ref[0]
+ except exception.ComputeHostNotFound:
+ raise webob.exc.HTTPNotFound(explanation=_("Host not found"))
+ instance_refs = db.instance_get_all_by_host(context,
+ compute_ref['host'])
+
+ # Getting total available/used resource
+ compute_ref = compute_ref['compute_node'][0]
+ resource = {'vcpus': compute_ref['vcpus'],
+ 'memory_mb': compute_ref['memory_mb'],
+ 'local_gb': compute_ref['local_gb'],
+ 'vcpus_used': compute_ref['vcpus_used'],
+ 'memory_mb_used': compute_ref['memory_mb_used'],
+ 'local_gb_used': compute_ref['local_gb_used']}
+ usage = dict()
+ if not instance_refs:
+ return {'host':
+ {'resource': resource, 'usage': usage}}
+
+ # Getting usage resource per project
+ project_ids = [i['project_id'] for i in instance_refs]
+ project_ids = list(set(project_ids))
+ for project_id in project_ids:
+ vcpus = [i['vcpus'] for i in instance_refs
+ if i['project_id'] == project_id]
+
+ mem = [i['memory_mb'] for i in instance_refs
+ if i['project_id'] == project_id]
+
+ disk = [i['root_gb'] + i['ephemeral_gb'] for i in instance_refs
+ if i['project_id'] == project_id]
+
+ usage[project_id] = {'vcpus': reduce(lambda x, y: x + y, vcpus),
+ 'memory_mb': reduce(lambda x, y: x + y, mem),
+ 'local_gb': reduce(lambda x, y: x + y, disk)}
+
+ return {'host': {'resource': resource, 'usage': usage}}
+
class Hosts(extensions.ExtensionDescriptor):
"""Admin-only host administration"""