summaryrefslogtreecommitdiffstats
path: root/nova/api
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2013-01-11 03:02:31 +0000
committerGerrit Code Review <review@openstack.org>2013-01-11 03:02:31 +0000
commitec120d52b57ad37f813f32a81ecc689a1bab6d56 (patch)
tree192ef6705a5810ce9c6277638d7051f59266e3b8 /nova/api
parentfabc6ec5d8eb09e6891637bd884e09da05288b6c (diff)
parent745335bc3c6c74d6988083a11c7267b9597f4838 (diff)
Merge "Move logic from os-api-host into compute"
Diffstat (limited to 'nova/api')
-rw-r--r--nova/api/openstack/compute/contrib/hosts.py259
1 files changed, 114 insertions, 145 deletions
diff --git a/nova/api/openstack/compute/contrib/hosts.py b/nova/api/openstack/compute/contrib/hosts.py
index 9812ceba3..52487c305 100644
--- a/nova/api/openstack/compute/contrib/hosts.py
+++ b/nova/api/openstack/compute/contrib/hosts.py
@@ -22,9 +22,7 @@ from xml.parsers import expat
from nova.api.openstack import extensions
from nova.api.openstack import wsgi
from nova.api.openstack import xmlutil
-from nova import availability_zones
-from nova.compute import api as compute_api
-from nova import db
+from nova import compute
from nova import exception
from nova.openstack.common import log as logging
@@ -94,140 +92,162 @@ class HostUpdateDeserializer(wsgi.XMLDeserializer):
return dict(body=updates)
-def _list_hosts(req):
- """Returns a summary list of hosts, optionally filtering
- by service type.
- """
- context = req.environ['nova.context']
- services = db.service_get_all(context, False)
- services = availability_zones.set_availability_zones(context, services)
- zone = ''
- if 'zone' in req.GET:
- zone = req.GET['zone']
- if zone:
- services = [s for s in services if s['availability_zone'] == zone]
- hosts = []
- for host in services:
- hosts.append({"host_name": host['host'], 'service': host['topic'],
- 'zone': host['availability_zone']})
- return hosts
-
-
-def check_host(fn):
- """Makes sure that the host exists."""
- def wrapped(self, req, id, *args, **kwargs):
- listed_hosts = _list_hosts(req)
- hosts = [h["host_name"] for h in listed_hosts]
- if id in hosts:
- return fn(self, req, id, *args, **kwargs)
- else:
- message = _("Host '%s' could not be found.") % id
- raise webob.exc.HTTPNotFound(explanation=message)
- return wrapped
-
-
class HostController(object):
"""The Hosts API controller for the OpenStack API."""
def __init__(self):
- self.api = compute_api.HostAPI()
+ self.api = compute.HostAPI()
super(HostController, self).__init__()
@wsgi.serializers(xml=HostIndexTemplate)
def index(self, req):
- authorize(req.environ['nova.context'])
- return {'hosts': _list_hosts(req)}
+ """
+ :returns: A dict in the format:
+
+ {'hosts': [{'host_name': 'some.host.name',
+ 'service': 'cells'},
+ {'host_name': 'some.other.host.name',
+ 'service': 'cells'},
+ {'host_name': 'some.celly.host.name',
+ 'service': 'cells'},
+ {'host_name': 'console1.host.com',
+ 'service': 'consoleauth'},
+ {'host_name': 'network1.host.com',
+ 'service': 'network'},
+ {'host_name': 'netwwork2.host.com',
+ 'service': 'network'},
+ {'host_name': 'sched1.host.com',
+ 'service': 'scheduler'},
+ {'host_name': 'sched2.host.com',
+ 'service': 'scheduler'},
+ {'host_name': 'vol1.host.com',
+ 'service': 'volume'}]}
+ """
+ context = req.environ['nova.context']
+ authorize(context)
+ zone = req.GET.get('zone', None)
+ data = self.api.list_hosts(context, zone)
+
+ return {'hosts': data}
@wsgi.serializers(xml=HostUpdateTemplate)
@wsgi.deserializers(xml=HostUpdateDeserializer)
- @check_host
def update(self, req, id, body):
- authorize(req.environ['nova.context'])
- update_values = {}
- for raw_key, raw_val in body.iteritems():
- key = raw_key.lower().strip()
- val = raw_val.lower().strip()
- if key == "status":
- if val in ("enable", "disable"):
- update_values['status'] = val.startswith("enable")
- else:
- explanation = _("Invalid status: '%s'") % raw_val
- raise webob.exc.HTTPBadRequest(explanation=explanation)
- elif key == "maintenance_mode":
- if val not in ['enable', 'disable']:
- explanation = _("Invalid mode: '%s'") % raw_val
- raise webob.exc.HTTPBadRequest(explanation=explanation)
- update_values['maintenance_mode'] = val == 'enable'
+ """
+ :param body: example format {'status': 'enable',
+ 'maintenance_mode': 'enable'}
+ :returns:
+ """
+ def read_enabled(orig_val, msg):
+ """
+ :param orig_val: A string with either 'enable' or 'disable'. May
+ be surrounded by whitespace, and case doesn't
+ matter
+ :param msg: The message to be passed to HTTPBadRequest. A single
+ %s will be replaced with orig_val.
+ :returns: True for 'enabled' and False for 'disabled'
+ """
+ val = orig_val.strip().lower()
+ if val == "enable":
+ return True
+ elif val == "disable":
+ return False
else:
- explanation = _("Invalid update setting: '%s'") % raw_key
- raise webob.exc.HTTPBadRequest(explanation=explanation)
-
- # this is for handling multiple settings at the same time:
- # the result dictionaries are merged in the first one.
- # Note: the 'host' key will always be the same so it's
- # okay that it gets overwritten.
- update_setters = {'status': self._set_enabled_status,
- 'maintenance_mode': self._set_host_maintenance}
- result = {}
- for key, value in update_values.iteritems():
- result.update(update_setters[key](req, id, value))
+ raise webob.exc.HTTPBadRequest(explanation=msg % orig_val)
+ context = req.environ['nova.context']
+ authorize(context)
+ # See what the user wants to 'update'
+ params = dict([(k.strip().lower(), v) for k, v in body.iteritems()])
+ orig_status = status = params.pop('status', None)
+ orig_maint_mode = maint_mode = params.pop('maintenance_mode', None)
+ # Validate the request
+ if len(params) > 0:
+ # Some extra param was passed. Fail.
+ explanation = _("Invalid update setting: '%s'") % params.keys()[0]
+ raise webob.exc.HTTPBadRequest(explanation=explanation)
+ if orig_status is not None:
+ status = read_enabled(orig_status, _("Invalid status: '%s'"))
+ if orig_maint_mode is not None:
+ maint_mode = read_enabled(orig_maint_mode, _("Invalid mode: '%s'"))
+ if status is None and maint_mode is None:
+ explanation = _("'status' or 'maintenance_mode' needed for "
+ "host update")
+ raise webob.exc.HTTPBadRequest(explanation=explanation)
+ # Make the calls and merge the results
+ result = {'host': id}
+ if status is not None:
+ result['status'] = self._set_enabled_status(context, id, status)
+ if maint_mode is not None:
+ result['maintenance_mode'] = self._set_host_maintenance(context,
+ id, maint_mode)
return result
- def _set_host_maintenance(self, req, host, mode=True):
+ def _set_host_maintenance(self, context, host_name, mode=True):
"""Start/Stop host maintenance window. On start, it triggers
guest VMs evacuation."""
- context = req.environ['nova.context']
- LOG.audit(_("Putting host %(host)s in maintenance "
+ LOG.audit(_("Putting host %(host_name)s in maintenance "
"mode %(mode)s.") % locals())
try:
- result = self.api.set_host_maintenance(context, host, mode)
+ result = self.api.set_host_maintenance(context, host_name, mode)
except NotImplementedError:
msg = _("Virt driver does not implement host maintenance mode.")
raise webob.exc.HTTPNotImplemented(explanation=msg)
- return {"host": host, "maintenance_mode": result}
+ except exception.NotFound as e:
+ raise webob.exc.HTTPNotFound(explanation=e.message)
+ if result not in ("on_maintenance", "off_maintenance"):
+ raise webob.exc.HTTPBadRequest(explanation=result)
+ return result
- def _set_enabled_status(self, req, host, enabled):
- """Sets the specified host's ability to accept new instances."""
- context = req.environ['nova.context']
- state = "enabled" if enabled else "disabled"
- LOG.audit(_("Setting host %(host)s to %(state)s.") % locals())
+ def _set_enabled_status(self, context, host_name, enabled):
+ """Sets the specified host's ability to accept new instances.
+ :param enabled: a boolean - if False no new VMs will be able to start
+ on the host"""
+ if enabled:
+ LOG.audit(_("Enabling host %s.") % host_name)
+ else:
+ LOG.audit(_("Disabling host %s.") % host_name)
try:
- result = self.api.set_host_enabled(context, host=host,
- enabled=enabled)
+ result = self.api.set_host_enabled(context, host_name=host_name,
+ enabled=enabled)
except NotImplementedError:
msg = _("Virt driver does not implement host disabled status.")
raise webob.exc.HTTPNotImplemented(explanation=msg)
- return {"host": host, "status": result}
+ except exception.NotFound as e:
+ raise webob.exc.HTTPNotFound(explanation=e.message)
+ if result not in ("enabled", "disabled"):
+ raise webob.exc.HTTPBadRequest(explanation=result)
+ return result
- def _host_power_action(self, req, host, action):
+ def _host_power_action(self, req, host_name, action):
"""Reboots, shuts down or powers up the host."""
context = req.environ['nova.context']
authorize(context)
try:
- result = self.api.host_power_action(context, host=host,
+ result = self.api.host_power_action(context, host_name=host_name,
action=action)
except NotImplementedError:
msg = _("Virt driver does not implement host power management.")
raise webob.exc.HTTPNotImplemented(explanation=msg)
- return {"host": host, "power_action": result}
+ except exception.NotFound as e:
+ raise webob.exc.HTTPNotFound(explanation=e.message)
+ return {"host": host_name, "power_action": result}
@wsgi.serializers(xml=HostActionTemplate)
def startup(self, req, id):
- return self._host_power_action(req, host=id, action="startup")
+ return self._host_power_action(req, host_name=id, action="startup")
@wsgi.serializers(xml=HostActionTemplate)
def shutdown(self, req, id):
- return self._host_power_action(req, host=id, action="shutdown")
+ return self._host_power_action(req, host_name=id, action="shutdown")
@wsgi.serializers(xml=HostActionTemplate)
def reboot(self, req, id):
- return self._host_power_action(req, host=id, action="reboot")
+ return self._host_power_action(req, host_name=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
+ :param id: hostname
:returns: expected to use HostShowTemplate.
ex.::
@@ -235,66 +255,15 @@ class HostController(object):
D: {'host': 'hostname','project': 'admin',
'cpu': 1, 'memory_mb': 2048, 'disk_gb': 30}
"""
- host = id
context = req.environ['nova.context']
- if not context.is_admin:
+ try:
+ data = self.api.describe_host(context, id)
+ except exception.NotFound as e:
+ raise webob.exc.HTTPNotFound(explanation=e.message)
+ except exception.AdminRequired:
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]
- resources = [{'resource': {'host': host, 'project': '(total)',
- 'cpu': compute_ref['vcpus'],
- 'memory_mb': compute_ref['memory_mb'],
- 'disk_gb': compute_ref['local_gb']}},
- {'resource': {'host': host, 'project': '(used_now)',
- 'cpu': compute_ref['vcpus_used'],
- 'memory_mb': compute_ref['memory_mb_used'],
- 'disk_gb': compute_ref['local_gb_used']}}]
-
- cpu_sum = 0
- mem_sum = 0
- hdd_sum = 0
- for i in instance_refs:
- cpu_sum += i['vcpus']
- mem_sum += i['memory_mb']
- hdd_sum += i['root_gb'] + i['ephemeral_gb']
-
- resources.append({'resource': {'host': host,
- 'project': '(used_max)',
- 'cpu': cpu_sum,
- 'memory_mb': mem_sum,
- 'disk_gb': hdd_sum}})
-
- # 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]
-
- resources.append({'resource': {'host': host,
- 'project': project_id,
- 'cpu': reduce(lambda x, y: x + y, vcpus),
- 'memory_mb': reduce(lambda x, y: x + y, mem),
- 'disk_gb': reduce(lambda x, y: x + y, disk)}})
-
- return {'host': resources}
+ return {'host': data}
class Hosts(extensions.ExtensionDescriptor):