summaryrefslogtreecommitdiffstats
path: root/nova/api
diff options
context:
space:
mode:
authorSandy Walsh <sandy.walsh@rackspace.com>2011-07-11 09:13:55 -0700
committerSandy Walsh <sandy.walsh@rackspace.com>2011-07-11 09:13:55 -0700
commit0c04ec998a474da14ecf809168c6d80eb6638206 (patch)
tree8e398ff04829209c38aea15fcc7825bec2245427 /nova/api
parente6ebcbd911467ed1a9a468a350c5488ac83811bd (diff)
parent5230b28d9120201741059f2bab588118fe9b1c25 (diff)
minor tweaks
Diffstat (limited to 'nova/api')
-rw-r--r--nova/api/ec2/cloud.py11
-rw-r--r--nova/api/ec2/metadatarequesthandler.py6
-rw-r--r--nova/api/openstack/contrib/hosts.py114
-rw-r--r--nova/api/openstack/images.py20
-rw-r--r--nova/api/openstack/servers.py10
5 files changed, 151 insertions, 10 deletions
diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py
index 9be30cf75..acfd1361c 100644
--- a/nova/api/ec2/cloud.py
+++ b/nova/api/ec2/cloud.py
@@ -166,6 +166,9 @@ class CloudController(object):
instance_ref['id'])
ec2_id = ec2utils.id_to_ec2_id(instance_ref['id'])
image_ec2_id = self.image_ec2_id(instance_ref['image_ref'])
+ security_groups = db.security_group_get_by_instance(ctxt,
+ instance_ref['id'])
+ security_groups = [x['name'] for x in security_groups]
data = {
'user-data': base64.b64decode(instance_ref['user_data']),
'meta-data': {
@@ -189,7 +192,7 @@ class CloudController(object):
'public-ipv4': floating_ip or '',
'public-keys': keys,
'reservation-id': instance_ref['reservation_id'],
- 'security-groups': '',
+ 'security-groups': security_groups,
'mpi': mpi}}
for image_type in ['kernel', 'ramdisk']:
@@ -1088,12 +1091,16 @@ class CloudController(object):
def _get_image(self, context, ec2_id):
try:
internal_id = ec2utils.ec2_id_to_id(ec2_id)
- return self.image_service.show(context, internal_id)
+ image = self.image_service.show(context, internal_id)
except (exception.InvalidEc2Id, exception.ImageNotFound):
try:
return self.image_service.show_by_name(context, ec2_id)
except exception.NotFound:
raise exception.ImageNotFound(image_id=ec2_id)
+ image_type = ec2_id.split('-')[0]
+ if self._image_type(image.get('container_format')) != image_type:
+ raise exception.ImageNotFound(image_id=ec2_id)
+ return image
def _format_image(self, image):
"""Convert from format defined by BaseImageService to S3 format."""
diff --git a/nova/api/ec2/metadatarequesthandler.py b/nova/api/ec2/metadatarequesthandler.py
index b70266a20..1dc275c90 100644
--- a/nova/api/ec2/metadatarequesthandler.py
+++ b/nova/api/ec2/metadatarequesthandler.py
@@ -35,6 +35,9 @@ FLAGS = flags.FLAGS
class MetadataRequestHandler(wsgi.Application):
"""Serve metadata from the EC2 API."""
+ def __init__(self):
+ self.cc = cloud.CloudController()
+
def print_data(self, data):
if isinstance(data, dict):
output = ''
@@ -68,12 +71,11 @@ class MetadataRequestHandler(wsgi.Application):
@webob.dec.wsgify(RequestClass=wsgi.Request)
def __call__(self, req):
- cc = cloud.CloudController()
remote_address = req.remote_addr
if FLAGS.use_forwarded_for:
remote_address = req.headers.get('X-Forwarded-For', remote_address)
try:
- meta_data = cc.get_metadata(remote_address)
+ meta_data = self.cc.get_metadata(remote_address)
except Exception:
LOG.exception(_('Failed to get metadata for ip: %s'),
remote_address)
diff --git a/nova/api/openstack/contrib/hosts.py b/nova/api/openstack/contrib/hosts.py
new file mode 100644
index 000000000..55e57e1a4
--- /dev/null
+++ b/nova/api/openstack/contrib/hosts.py
@@ -0,0 +1,114 @@
+# Copyright (c) 2011 Openstack, LLC.
+# All Rights Reserved.
+#
+# 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.
+
+"""The hosts admin extension."""
+
+import webob.exc
+
+from nova import compute
+from nova import exception
+from nova import flags
+from nova import log as logging
+from nova.api.openstack import common
+from nova.api.openstack import extensions
+from nova.api.openstack import faults
+from nova.scheduler import api as scheduler_api
+
+
+LOG = logging.getLogger("nova.api.hosts")
+FLAGS = flags.FLAGS
+
+
+def _list_hosts(req, service=None):
+ """Returns a summary list of hosts, optionally filtering
+ by service type.
+ """
+ context = req.environ['nova.context']
+ hosts = scheduler_api.get_host_list(context)
+ if service:
+ hosts = [host for host in hosts
+ if host["service"] == service]
+ return hosts
+
+
+def check_host(fn):
+ """Makes sure that the host exists."""
+ def wrapped(self, req, id, service=None, *args, **kwargs):
+ listed_hosts = _list_hosts(req, service)
+ hosts = [h["host_name"] for h in listed_hosts]
+ if id in hosts:
+ return fn(self, req, id, *args, **kwargs)
+ else:
+ raise exception.HostNotFound(host=id)
+ return wrapped
+
+
+class HostController(object):
+ """The Hosts API controller for the OpenStack API."""
+ def __init__(self):
+ self.compute_api = compute.API()
+ super(HostController, self).__init__()
+
+ def index(self, req):
+ return {'hosts': _list_hosts(req)}
+
+ @check_host
+ def update(self, req, id, body):
+ for raw_key, raw_val in body.iteritems():
+ key = raw_key.lower().strip()
+ val = raw_val.lower().strip()
+ # NOTE: (dabo) Right now only 'status' can be set, but other
+ # actions may follow.
+ if key == "status":
+ if val[:6] in ("enable", "disabl"):
+ return self._set_enabled_status(req, id,
+ enabled=(val.startswith("enable")))
+ else:
+ explanation = _("Invalid status: '%s'") % raw_val
+ raise webob.exc.HTTPBadRequest(explanation=explanation)
+ else:
+ explanation = _("Invalid update setting: '%s'") % raw_key
+ raise webob.exc.HTTPBadRequest(explanation=explanation)
+
+ 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())
+ result = self.compute_api.set_host_enabled(context, host=host,
+ enabled=enabled)
+ return {"host": host, "status": result}
+
+
+class Hosts(extensions.ExtensionDescriptor):
+ def get_name(self):
+ return "Hosts"
+
+ def get_alias(self):
+ return "os-hosts"
+
+ def get_description(self):
+ return "Host administration"
+
+ def get_namespace(self):
+ return "http://docs.openstack.org/ext/hosts/api/v1.1"
+
+ def get_updated(self):
+ return "2011-06-29T00:00:00+00:00"
+
+ def get_resources(self):
+ resources = [extensions.ResourceExtension('os-hosts', HostController(),
+ collection_actions={'update': 'PUT'}, member_actions={})]
+ return resources
diff --git a/nova/api/openstack/images.py b/nova/api/openstack/images.py
index bde9507c8..348d300f2 100644
--- a/nova/api/openstack/images.py
+++ b/nova/api/openstack/images.py
@@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+import urlparse
import os.path
import webob.exc
@@ -23,7 +24,6 @@ from nova import exception
from nova import flags
import nova.image
from nova import log
-from nova import utils
from nova.api.openstack import common
from nova.api.openstack import faults
from nova.api.openstack import image_metadata
@@ -246,13 +246,23 @@ class ControllerV11(Controller):
msg = _("Expected serverRef attribute on server entity.")
raise webob.exc.HTTPBadRequest(explanation=msg)
- head, tail = os.path.split(server_ref)
-
- if head and head != os.path.join(req.application_url, 'servers'):
+ if not server_ref.startswith('http'):
+ return server_ref
+
+ passed = urlparse.urlparse(server_ref)
+ expected = urlparse.urlparse(req.application_url)
+ version = expected.path.split('/')[1]
+ expected_prefix = "/%s/servers/" % version
+ _empty, _sep, server_id = passed.path.partition(expected_prefix)
+ scheme_ok = passed.scheme == expected.scheme
+ host_ok = passed.hostname == expected.hostname
+ port_ok = (passed.port == expected.port or
+ passed.port == FLAGS.osapi_port)
+ if not (scheme_ok and port_ok and host_ok and server_id):
msg = _("serverRef must match request url")
raise webob.exc.HTTPBadRequest(explanation=msg)
- return tail
+ return server_id
def _get_extra_properties(self, req, data):
server_ref = data['image']['serverRef']
diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py
index fc1ab8d46..eacc2109f 100644
--- a/nova/api/openstack/servers.py
+++ b/nova/api/openstack/servers.py
@@ -176,7 +176,7 @@ class Controller(object):
'confirmResize': self._action_confirm_resize,
'revertResize': self._action_revert_resize,
'rebuild': self._action_rebuild,
- }
+ 'migrate': self._action_migrate}
for key in actions.keys():
if key in body:
@@ -220,6 +220,14 @@ class Controller(object):
return faults.Fault(exc.HTTPUnprocessableEntity())
return exc.HTTPAccepted()
+ def _action_migrate(self, input_dict, req, id):
+ try:
+ self.compute_api.resize(req.environ['nova.context'], id)
+ except Exception, e:
+ LOG.exception(_("Error in migrate %s"), e)
+ return faults.Fault(exc.HTTPBadRequest())
+ return exc.HTTPAccepted()
+
@scheduler_api.redirect_handler
def lock(self, req, id):
"""