diff options
| author | Jenkins <jenkins@review.openstack.org> | 2013-01-11 03:02:31 +0000 |
|---|---|---|
| committer | Gerrit Code Review <review@openstack.org> | 2013-01-11 03:02:31 +0000 |
| commit | ec120d52b57ad37f813f32a81ecc689a1bab6d56 (patch) | |
| tree | 192ef6705a5810ce9c6277638d7051f59266e3b8 /nova/api | |
| parent | fabc6ec5d8eb09e6891637bd884e09da05288b6c (diff) | |
| parent | 745335bc3c6c74d6988083a11c7267b9597f4838 (diff) | |
Merge "Move logic from os-api-host into compute"
Diffstat (limited to 'nova/api')
| -rw-r--r-- | nova/api/openstack/compute/contrib/hosts.py | 259 |
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): |
