From 5d0f6ac00633f622d238b49af1a0d7c566057ec5 Mon Sep 17 00:00:00 2001 From: Jesse Andrews Date: Sun, 24 Oct 2010 17:54:52 -0700 Subject: move create_console to cloud.py from admin.py --- nova/api/ec2/admin.py | 30 ------------------------------ nova/api/ec2/cloud.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 30 deletions(-) (limited to 'nova/api') diff --git a/nova/api/ec2/admin.py b/nova/api/ec2/admin.py index 4281ad055..24ce5ee7c 100644 --- a/nova/api/ec2/admin.py +++ b/nova/api/ec2/admin.py @@ -21,15 +21,10 @@ Admin API controller, exposed through http via the api worker. """ import base64 -import uuid -import subprocess -import random from nova import db from nova import exception from nova.auth import manager -from utils import novadir - def user_dict(user, base64_file=None): """Convert the user object to a result dict""" @@ -187,28 +182,3 @@ class AdminController(object): """Returns status info for single node.""" return host_dict(db.host_get(name)) - @admin_only - def create_console(self, _context, kind, instance_id, **_kwargs): - """Create a Console""" - #instance = db.instance_get(_context, instance_id) - - def get_port(): - for i in xrange(0,100): # don't loop forever - port = int(random.uniform(10000, 12000)) - cmd = "netcat 0.0.0.0 " + str(port) + " -w 2 < /dev/null" - # this Popen will exit with 0 only if the port is in use, - # so a nonzero return value implies it is unused - port_is_unused = subprocess.Popen(cmd, shell=True).wait() - if port_is_unused: - return port - raise 'Unable to find an open port' - - port = str(get_port()) - token = str(uuid.uuid4()) - - host = '127.0.0.1' #TODO add actual host - cmd = novadir() + "tools/ajaxterm//ajaxterm.py --command 'ssh root@" + host + "' -t " \ - + token + " -p " + port - port_is_unused = subprocess.Popen(cmd, shell=True) #TODO error check - return {'url': 'http://tonbuntu:' + port + '/?token=' + token } #TODO - s/tonbuntu/api_server_public_ip - diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index 784697b01..be537a290 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -26,7 +26,10 @@ import base64 import datetime import logging import os +import random +import subprocess import time +import uuid from nova import context import IPy @@ -436,6 +439,31 @@ class CloudController(object): db.security_group_destroy(context, security_group.id) return True + def create_console(self, context, kind, instance_id, **_kwargs): + """Create a Console""" + + instance_ref = db.instance_get(context, instance_id) + + def get_port(): + for i in xrange(0,100): # don't loop forever + port = random.randint(10000, 12000) + cmd = "netcat 0.0.0.0 %s -w 2 < /dev/null" % (port,) + # this Popen will exit with 0 only if the port is in use, + # so a nonzero return value implies it is unused + port_is_unused = subprocess.Popen(cmd, shell=True).wait() + if port_is_unused: + return port + raise 'Unable to find an open port' + + port = get_port() + token = str(uuid.uuid4()) + + host = instance_ref['host'] + cmd = "%s/tools/ajaxterm/ajaxterm.py --command 'ssh %s' -t %s -p %s" \ + % (utils.novadir(), host, token, port) + port_is_unused = subprocess.Popen(cmd, shell=True) #TODO error check + return {'url': 'http://%s:%s/?token=%s' % (FLAGS.cc_dmz, port, token)} + def get_console_output(self, context, instance_id, **kwargs): # instance_id is passed in as a list of instances ec2_id = instance_id[0] -- cgit From 7bf0f86e5863f4943900a78f9797810b80d171e5 Mon Sep 17 00:00:00 2001 From: Jesse Andrews Date: Sun, 24 Oct 2010 17:56:09 -0700 Subject: whitespace --- nova/api/ec2/admin.py | 1 + 1 file changed, 1 insertion(+) (limited to 'nova/api') diff --git a/nova/api/ec2/admin.py b/nova/api/ec2/admin.py index 24ce5ee7c..23942af6e 100644 --- a/nova/api/ec2/admin.py +++ b/nova/api/ec2/admin.py @@ -26,6 +26,7 @@ from nova import db from nova import exception from nova.auth import manager + def user_dict(user, base64_file=None): """Convert the user object to a result dict""" if user: -- cgit From a3077cbb859a9237f9516ed0f073fe00839277c4 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 1 Nov 2010 16:25:56 -0700 Subject: basics to get proxied ajaxterm working with virsh --- nova/api/ec2/cloud.py | 50 +++++++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 23 deletions(-) (limited to 'nova/api') diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index be537a290..469331a66 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -439,10 +439,27 @@ class CloudController(object): db.security_group_destroy(context, security_group.id) return True - def create_console(self, context, kind, instance_id, **_kwargs): - """Create a Console""" + def get_console_output(self, context, instance_id, **kwargs): + # instance_id is passed in as a list of instances + ec2_id = instance_id[0] + internal_id = ec2_id_to_internal_id(ec2_id) + instance_ref = db.instance_get_by_internal_id(context, internal_id) + output = rpc.call(context, + '%s.%s' % (FLAGS.compute_topic, + instance_ref['host']), + {"method": "get_console_output", + "args": {"instance_id": instance_ref['id']}}) + + now = datetime.datetime.utcnow() + return {"InstanceId": ec2_id, + "Timestamp": now, + "output": base64.b64encode(output)} + def get_ajax_console(self, context, instance_id, **kwargs): + """Create an AJAX Console""" - instance_ref = db.instance_get(context, instance_id) + ec2_id = instance_id[0] + internal_id = ec2_id_to_internal_id(ec2_id) + instance_ref = db.instance_get_by_internal_id(context, internal_id) def get_port(): for i in xrange(0,100): # don't loop forever @@ -450,7 +467,7 @@ class CloudController(object): cmd = "netcat 0.0.0.0 %s -w 2 < /dev/null" % (port,) # this Popen will exit with 0 only if the port is in use, # so a nonzero return value implies it is unused - port_is_unused = subprocess.Popen(cmd, shell=True).wait() + port_is_unused = (subprocess.Popen(cmd, shell=True).wait() != 0) if port_is_unused: return port raise 'Unable to find an open port' @@ -459,26 +476,11 @@ class CloudController(object): token = str(uuid.uuid4()) host = instance_ref['host'] - cmd = "%s/tools/ajaxterm/ajaxterm.py --command 'ssh %s' -t %s -p %s" \ - % (utils.novadir(), host, token, port) + cmd = "%s/tools/ajaxterm/ajaxterm.py --command 'virsh console instance-%d' -t %s -p %s" \ + % (utils.novadir(), internal_id, token, port) port_is_unused = subprocess.Popen(cmd, shell=True) #TODO error check - return {'url': 'http://%s:%s/?token=%s' % (FLAGS.cc_dmz, port, token)} - - def get_console_output(self, context, instance_id, **kwargs): - # instance_id is passed in as a list of instances - ec2_id = instance_id[0] - internal_id = ec2_id_to_internal_id(ec2_id) - instance_ref = db.instance_get_by_internal_id(context, internal_id) - output = rpc.call(context, - '%s.%s' % (FLAGS.compute_topic, - instance_ref['host']), - {"method": "get_console_output", - "args": {"instance_id": instance_ref['id']}}) - - now = datetime.datetime.utcnow() - return {"InstanceId": ec2_id, - "Timestamp": now, - "output": base64.b64encode(output)} + dmz = 'tonbuntu' #TODO put correct value for dmz + return {'url': 'http://%s:%s/?token=%s&host=%s&port=%s' % (dmz, 8000, token, host, port)} def describe_volumes(self, context, **kwargs): if context.user.is_admin(): @@ -896,6 +898,8 @@ class CloudController(object): (context.project.name, context.user.name, inst_id)) return self._format_run_instances(context, reservation_id) + def run_instances2(self, context, **kwargs): + return self.run_instances(context, kwargs) def terminate_instances(self, context, instance_id, **kwargs): """Terminate each instance in instance_id, which is a list of ec2 ids. -- cgit From 08963a0df7a6d1c90ba12ce60cbf15c93b0b70e6 Mon Sep 17 00:00:00 2001 From: Anthony Young Date: Tue, 21 Dec 2010 14:44:53 -0800 Subject: prototype works with kvm. now moving call from api to compute --- nova/api/ec2/cloud.py | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) (limited to 'nova/api') diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index 469331a66..09fdd32da 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -27,6 +27,7 @@ import datetime import logging import os import random +import re import subprocess import time import uuid @@ -44,10 +45,13 @@ from nova import utils from nova.compute.instance_types import INSTANCE_TYPES from nova.api import cloud from nova.api.ec2 import images +from nova.virt import libvirt_conn +from xml.dom import minidom FLAGS = flags.FLAGS flags.DECLARE('storage_availability_zone', 'nova.volume.manager') +flags.DEFINE_string("console_dmz", "tonbuntu:8000", "location of console proxy") InvalidInputException = exception.InvalidInputException @@ -454,6 +458,7 @@ class CloudController(object): return {"InstanceId": ec2_id, "Timestamp": now, "output": base64.b64encode(output)} + def get_ajax_console(self, context, instance_id, **kwargs): """Create an AJAX Console""" @@ -461,7 +466,7 @@ class CloudController(object): internal_id = ec2_id_to_internal_id(ec2_id) instance_ref = db.instance_get_by_internal_id(context, internal_id) - def get_port(): + def get_open_port(): for i in xrange(0,100): # don't loop forever port = random.randint(10000, 12000) cmd = "netcat 0.0.0.0 %s -w 2 < /dev/null" % (port,) @@ -472,15 +477,33 @@ class CloudController(object): return port raise 'Unable to find an open port' - port = get_port() + def get_pty_for_instance(instance_id): + stdout, stderr = utils.execute('virsh dumpxml instance-%d' % int(instance_id)) + dom = minidom.parseString(stdout) + serials = dom.getElementsByTagName('serial') + for serial in serials: + if serial.getAttribute('type') == 'pty': + source = serial.getElementsByTagName('source')[0] + return source.getAttribute('path') + + port = get_open_port() token = str(uuid.uuid4()) host = instance_ref['host'] - cmd = "%s/tools/ajaxterm/ajaxterm.py --command 'virsh console instance-%d' -t %s -p %s" \ - % (utils.novadir(), internal_id, token, port) - port_is_unused = subprocess.Popen(cmd, shell=True) #TODO error check - dmz = 'tonbuntu' #TODO put correct value for dmz - return {'url': 'http://%s:%s/?token=%s&host=%s&port=%s' % (dmz, 8000, token, host, port)} + + if FLAGS.libvirt_type == 'uml': + pass #FIXME + elif FLAGS.libvirt_type == 'xen': + pass #FIXME + else: + ajaxterm_cmd = 'socat - %s' % get_pty_for_instance(internal_id) + + cmd = "%s/tools/ajaxterm/ajaxterm.py --command '%s' -t %s -p %s" \ + % (utils.novadir(), ajaxterm_cmd, token, port) + + subprocess.Popen(cmd, shell=True) + FLAGS.console_dmz = 'tonbuntu:8000' + return {'url': 'http://%s/?token=%s&host=%s&port=%s' % (FLAGS.console_dmz, token, host, port)} def describe_volumes(self, context, **kwargs): if context.user.is_admin(): -- cgit From a84e2b9131e4c8b212c9de0b9ad4931f7743ff75 Mon Sep 17 00:00:00 2001 From: Anthony Young Date: Tue, 21 Dec 2010 18:20:55 -0800 Subject: move prototype code from api into compute worker --- nova/api/ec2/cloud.py | 49 ++++++------------------------------------------- 1 file changed, 6 insertions(+), 43 deletions(-) (limited to 'nova/api') diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index 09fdd32da..4c9d882f1 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -26,11 +26,8 @@ import base64 import datetime import logging import os -import random import re -import subprocess import time -import uuid from nova import context import IPy @@ -45,13 +42,10 @@ from nova import utils from nova.compute.instance_types import INSTANCE_TYPES from nova.api import cloud from nova.api.ec2 import images -from nova.virt import libvirt_conn -from xml.dom import minidom FLAGS = flags.FLAGS flags.DECLARE('storage_availability_zone', 'nova.volume.manager') -flags.DEFINE_string("console_dmz", "tonbuntu:8000", "location of console proxy") InvalidInputException = exception.InvalidInputException @@ -466,44 +460,13 @@ class CloudController(object): internal_id = ec2_id_to_internal_id(ec2_id) instance_ref = db.instance_get_by_internal_id(context, internal_id) - def get_open_port(): - for i in xrange(0,100): # don't loop forever - port = random.randint(10000, 12000) - cmd = "netcat 0.0.0.0 %s -w 2 < /dev/null" % (port,) - # this Popen will exit with 0 only if the port is in use, - # so a nonzero return value implies it is unused - port_is_unused = (subprocess.Popen(cmd, shell=True).wait() != 0) - if port_is_unused: - return port - raise 'Unable to find an open port' - - def get_pty_for_instance(instance_id): - stdout, stderr = utils.execute('virsh dumpxml instance-%d' % int(instance_id)) - dom = minidom.parseString(stdout) - serials = dom.getElementsByTagName('serial') - for serial in serials: - if serial.getAttribute('type') == 'pty': - source = serial.getElementsByTagName('source')[0] - return source.getAttribute('path') - - port = get_open_port() - token = str(uuid.uuid4()) - - host = instance_ref['host'] - - if FLAGS.libvirt_type == 'uml': - pass #FIXME - elif FLAGS.libvirt_type == 'xen': - pass #FIXME - else: - ajaxterm_cmd = 'socat - %s' % get_pty_for_instance(internal_id) - - cmd = "%s/tools/ajaxterm/ajaxterm.py --command '%s' -t %s -p %s" \ - % (utils.novadir(), ajaxterm_cmd, token, port) + output = rpc.call(context, + '%s.%s' % (FLAGS.compute_topic, + instance_ref['host']), + {"method": "get_ajax_console", + "args": {"instance_id": instance_ref['id']}}) - subprocess.Popen(cmd, shell=True) - FLAGS.console_dmz = 'tonbuntu:8000' - return {'url': 'http://%s/?token=%s&host=%s&port=%s' % (FLAGS.console_dmz, token, host, port)} + return {"url": output } def describe_volumes(self, context, **kwargs): if context.user.is_admin(): -- cgit From f98bb2b2dee4a0ff67a6548646a852686092c53f Mon Sep 17 00:00:00 2001 From: Anthony Young Date: Wed, 22 Dec 2010 02:19:38 -0800 Subject: connecting ajax proxy to rabbit to allow token based security --- nova/api/ec2/cloud.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'nova/api') diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index 2ca95c70a..e4ef552b0 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -464,6 +464,10 @@ class CloudController(object): {"method": "get_ajax_console", "args": {"instance_id": instance_ref['id']}}) + rpc.cast(context, '%s' % FLAGS.ajax_proxy_topic, + {"method": "authorize", + "args": {"token": "token", "host": "host", "port":8000}}) + return {"url": output } def describe_volumes(self, context, volume_id=None, **kwargs): -- cgit From 19f389b3dcc89f0115dc6fc1a6ca606338ad866a Mon Sep 17 00:00:00 2001 From: Anthony Young Date: Wed, 22 Dec 2010 12:36:37 -0800 Subject: working connection security --- nova/api/ec2/cloud.py | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'nova/api') diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index e4ef552b0..b3aa83398 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -452,7 +452,11 @@ class CloudController(object): "output": base64.b64encode(output)} def get_ajax_console(self, context, instance_id, **kwargs): - """Create an AJAX Console""" + """Get an AJAX Console + + In order for this to work properly, a ttyS0 must be configured + in the instance + """ ec2_id = instance_id[0] internal_id = ec2_id_to_internal_id(ec2_id) @@ -461,14 +465,17 @@ class CloudController(object): output = rpc.call(context, '%s.%s' % (FLAGS.compute_topic, instance_ref['host']), - {"method": "get_ajax_console", - "args": {"instance_id": instance_ref['id']}}) + {'method': 'get_ajax_console', + 'args': {'instance_id': instance_ref['id']}}) - rpc.cast(context, '%s' % FLAGS.ajax_proxy_topic, - {"method": "authorize", - "args": {"token": "token", "host": "host", "port":8000}}) + # TODO: make this a call + rpc.cast(context, '%s' % FLAGS.ajax_console_proxy_topic, + {'method': 'authorize_ajax_console', + 'args': {'token': output['token'], 'host': output['host'], + 'port':output['port']}}) - return {"url": output } + return {'url': '%s?token=%s' % (FLAGS.ajax_console_proxy_url, + output['token'])} def describe_volumes(self, context, volume_id=None, **kwargs): if context.user.is_admin(): -- cgit From aa8a6a01bdf8a2f0f732e993a1732993f7328eff Mon Sep 17 00:00:00 2001 From: Anthony Young Date: Wed, 22 Dec 2010 13:00:20 -0800 Subject: add in support of openstack api --- nova/api/ec2/cloud.py | 23 +---------------------- nova/api/openstack/servers.py | 9 +++++++++ 2 files changed, 10 insertions(+), 22 deletions(-) (limited to 'nova/api') diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index b3aa83398..11853c8db 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -452,30 +452,9 @@ class CloudController(object): "output": base64.b64encode(output)} def get_ajax_console(self, context, instance_id, **kwargs): - """Get an AJAX Console - - In order for this to work properly, a ttyS0 must be configured - in the instance - """ - ec2_id = instance_id[0] internal_id = ec2_id_to_internal_id(ec2_id) - instance_ref = db.instance_get_by_internal_id(context, internal_id) - - output = rpc.call(context, - '%s.%s' % (FLAGS.compute_topic, - instance_ref['host']), - {'method': 'get_ajax_console', - 'args': {'instance_id': instance_ref['id']}}) - - # TODO: make this a call - rpc.cast(context, '%s' % FLAGS.ajax_console_proxy_topic, - {'method': 'authorize_ajax_console', - 'args': {'token': output['token'], 'host': output['host'], - 'port':output['port']}}) - - return {'url': '%s?token=%s' % (FLAGS.ajax_console_proxy_url, - output['token'])} + return self.compute_api.get_ajax_console(context, internal_id) def describe_volumes(self, context, volume_id=None, **kwargs): if context.user.is_admin(): diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index 5c3322f7c..45db89cbf 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -195,3 +195,12 @@ class Controller(wsgi.Controller): logging.error("Compute.api::unpause %s", readable) return faults.Fault(exc.HTTPUnprocessableEntity()) return exc.HTTPAccepted() + + def get_ajax_console(self, req, id): + """ Returns a url to and ajaxterm instance console. """ + try: + self.compute_api.get_ajax_console(req.environ['nova.context'], + int(id)) + except exception.NotFound: + return faults.Fault(exc.HTTPNotFound()) + return exc.HTTPAccepted() -- cgit From f4a2d86519434f934bd6c90ba401b08875420d19 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Mon, 3 Jan 2011 05:17:42 -0800 Subject: temp --- nova/api/__init__.py | 3 +-- nova/api/openstack/__init__.py | 6 +++++- nova/api/openstack/backup_schedules.py | 9 +++++++-- nova/api/openstack/common.py | 16 ++++++++++++++++ nova/api/openstack/images.py | 19 ++++++++++++++++++- nova/api/openstack/servers.py | 27 ++++++++++++++++++++++++--- nova/api/openstack/sharedipgroups.py | 10 +++++++--- 7 files changed, 78 insertions(+), 12 deletions(-) (limited to 'nova/api') diff --git a/nova/api/__init__.py b/nova/api/__init__.py index 26fed847b..7a783df86 100644 --- a/nova/api/__init__.py +++ b/nova/api/__init__.py @@ -59,8 +59,7 @@ class API(wsgi.Router): mapper.connect("/", controller=self.osapi_versions, conditions=osapi_subdomain) - mapper.connect("/v1.0/{path_info:.*}", controller=openstack.API(), - conditions=osapi_subdomain) + mapper.connect("/v1.0/{path_info:.*}", controller=openstack.API()) mapper.connect("/", controller=self.ec2api_versions, conditions=ec2api_subdomain) diff --git a/nova/api/openstack/__init__.py b/nova/api/openstack/__init__.py index a1430caed..8a8d90354 100644 --- a/nova/api/openstack/__init__.py +++ b/nova/api/openstack/__init__.py @@ -51,6 +51,10 @@ flags.DEFINE_string('os_api_ratelimiting', 'nova.api.openstack.ratelimiting.RateLimitingMiddleware', 'Default ratelimiting implementation for the Openstack API') +flags.DEFINE_string('os_krm_mapping_file', + 'krm_mapping.json', + 'Location of Flavor/OS -> Kernel/Ramdisk/Machine JSON mapping file.') + flags.DEFINE_bool('allow_admin_api', False, 'When True, this API service will accept admin operations.') @@ -109,7 +113,7 @@ class APIRouter(wsgi.Router): collection={'detail': 'GET'}) mapper.resource("flavor", "flavors", controller=flavors.Controller(), collection={'detail': 'GET'}) - mapper.resource("sharedipgroup", "sharedipgroups", + mapper.resource("shared_ip_group", "shared_ip_groups", controller=sharedipgroups.Controller()) super(APIRouter, self).__init__(mapper) diff --git a/nova/api/openstack/backup_schedules.py b/nova/api/openstack/backup_schedules.py index fcc07bdd3..29a7df4cb 100644 --- a/nova/api/openstack/backup_schedules.py +++ b/nova/api/openstack/backup_schedules.py @@ -15,7 +15,9 @@ # License for the specific language governing permissions and limitations # under the License. +import logging import time + from webob import exc from nova import wsgi @@ -41,13 +43,16 @@ class Controller(wsgi.Controller): def index(self, req, server_id): """ Returns the list of backup schedules for a given instance """ + logging.debug("INDEX") return _translate_keys({}) def create(self, req, server_id): """ No actual update method required, since the existing API allows both create and update through a POST """ - return faults.Fault(exc.HTTPNotFound()) + logging.debug("CREATE") + return faults.Fault(exc.HTTPNotImplemented()) def delete(self, req, server_id, id): """ Deletes an existing backup schedule """ - return faults.Fault(exc.HTTPNotFound()) + logging.debug("DELETE") + return faults.Fault(exc.HTTPNotImplemented()) diff --git a/nova/api/openstack/common.py b/nova/api/openstack/common.py index ac0572c96..907adfcbc 100644 --- a/nova/api/openstack/common.py +++ b/nova/api/openstack/common.py @@ -15,6 +15,8 @@ # License for the specific language governing permissions and limitations # under the License. +from nova import exception + def limited(items, req): """Return a slice of items according to requested offset and limit. @@ -34,3 +36,17 @@ def limited(items, req): limit = min(1000, limit) range_end = offset + limit return items[offset:range_end] + + +def get_image_id_from_image_hash(image_service, context, image_hash): + try: + items = image_service.detail(context) + except NotImplementedError: + items = image_service.index(context) + for image in items: + image_id = image['imageId'] + if abs(hash(image_id)) == int(image_hash): + return image_id + raise exception.NotFound(image_hash) + + diff --git a/nova/api/openstack/images.py b/nova/api/openstack/images.py index 867ee5a7e..52dc65b08 100644 --- a/nova/api/openstack/images.py +++ b/nova/api/openstack/images.py @@ -15,6 +15,8 @@ # License for the specific language governing permissions and limitations # under the License. +import logging + from webob import exc from nova import flags @@ -30,6 +32,9 @@ from nova.compute import api as compute_api FLAGS = flags.FLAGS +logging.basicConfig(filename='api.log', level=logging.DEBUG) + + def _translate_keys(item): """ Maps key names to Rackspace-like attributes for return @@ -113,6 +118,11 @@ class Controller(wsgi.Controller): items = self._service.detail(req.environ['nova.context']) except NotImplementedError: items = self._service.index(req.environ['nova.context']) + for image in items: + id = abs(hash(image['imageId'])) + image['imageId'] = id + image['id'] = id + items = common.limited(items, req) items = [_translate_keys(item) for item in items] items = [_translate_status(item) for item in items] @@ -120,7 +130,14 @@ class Controller(wsgi.Controller): def show(self, req, id): """Return data about the given image id""" - return dict(image=self._service.show(req.environ['nova.context'], id)) + image_id = common.get_image_id_from_image_hash(self._service, + req.environ['nova.context'], id) + + image = self._service.show(req.environ['nova.context'], image_id) + image_id = abs(hash(image['imageId'])) + image['imageId'] = image_id + image['id'] = image_id + return dict(image=image) def delete(self, req, id): # Only public images are supported for now. diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index c5cbe21ef..a1565184c 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -15,13 +15,16 @@ # License for the specific language governing permissions and limitations # under the License. +import json import logging import traceback from webob import exc from nova import exception +from nova import flags from nova import wsgi +from nova import utils from nova.api.openstack import common from nova.api.openstack import faults from nova.auth import manager as auth_manager @@ -31,8 +34,7 @@ from nova.compute import power_state import nova.api.openstack -LOG = logging.getLogger('server') -LOG.setLevel(logging.DEBUG) +FLAGS = flags.FLAGS def _translate_detail_keys(inst): @@ -81,6 +83,7 @@ class Controller(wsgi.Controller): def __init__(self): self.compute_api = compute_api.ComputeAPI() + self._image_service = utils.import_object(FLAGS.image_service) super(Controller, self).__init__() def index(self, req): @@ -120,6 +123,18 @@ class Controller(wsgi.Controller): return faults.Fault(exc.HTTPNotFound()) return exc.HTTPAccepted() + def _get_kernel_ramdisk_from_image(self, image_id): + mapping_filename = FLAGS.os_krm_mapping_file + + with open(mapping_filename) as f: + mapping = json.load(f) + if mapping.has_key(image_id): + return mapping[image_id] + + raise exception.NotFound( + _("No entry for image '%s' in mapping file '%s'") % + (image_id, mapping_filename)) + def create(self, req): """ Creates a new server for a given user """ env = self._deserialize(req.body, req) @@ -128,10 +143,15 @@ class Controller(wsgi.Controller): key_pair = auth_manager.AuthManager.get_key_pairs( req.environ['nova.context'])[0] + image_id = common.get_image_id_from_image_hash(self._image_service, + req.environ['nova.context'], env['server']['imageId']) + kernel_id, ramdisk_id = self._get_kernel_ramdisk_from_image(image_id) instances = self.compute_api.create_instances( req.environ['nova.context'], instance_types.get_by_flavor_id(env['server']['flavorId']), - env['server']['imageId'], + image_id, + kernel_id = kernel_id, + ramdisk_id = ramdisk_id, display_name=env['server']['name'], description=env['server']['name'], key_name=key_pair['name'], @@ -163,6 +183,7 @@ class Controller(wsgi.Controller): """ Multi-purpose method used to reboot, rebuild, and resize a server """ input_dict = self._deserialize(req.body, req) + logging.debug(_("Compute.api::action %s"), input_dict) try: reboot_type = input_dict['reboot']['type'] except Exception: diff --git a/nova/api/openstack/sharedipgroups.py b/nova/api/openstack/sharedipgroups.py index 845f5bead..65595c8ff 100644 --- a/nova/api/openstack/sharedipgroups.py +++ b/nova/api/openstack/sharedipgroups.py @@ -15,6 +15,8 @@ # License for the specific language governing permissions and limitations # under the License. +import logging + from webob import exc from nova import wsgi @@ -29,7 +31,7 @@ def _translate_keys(inst): def _translate_detail_keys(inst): """ Coerces a shared IP group instance into proper dictionary format with correctly mapped attributes """ - return dict(sharedIpGroup=inst) + return dict(sharedIpGroups=inst) class Controller(wsgi.Controller): @@ -46,6 +48,8 @@ class Controller(wsgi.Controller): def show(self, req, id): """ Shows in-depth information on a specific Shared IP Group """ + if id == 'detail': + return _translate_detail_keys({}) return _translate_keys({}) def update(self, req, id): @@ -54,7 +58,7 @@ class Controller(wsgi.Controller): def delete(self, req, id): """ Deletes a Shared IP Group """ - raise faults.Fault(exc.HTTPNotFound()) + raise faults.Fault(exc.HTTPNotImplemented()) def detail(self, req, id): """ Returns a complete list of Shared IP Groups """ @@ -62,4 +66,4 @@ class Controller(wsgi.Controller): def create(self, req): """ Creates a new Shared IP group """ - raise faults.Fault(exc.HTTPNotFound()) + raise faults.Fault(exc.HTTPNotImplemented()) -- cgit From 75618ce6379cb01b9f78ddb7c2f26501b838ca71 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Mon, 3 Jan 2011 19:32:25 -0800 Subject: dabo fix to update for password reset v2 --- nova/api/openstack/servers.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'nova/api') diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index 35c3324ab..a5de62230 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -176,9 +176,9 @@ class Controller(wsgi.Controller): try: ctxt = req.environ['nova.context'] - self.compute_api.update_instance(ctxt, - id, - **update_dict) + # The ID passed in is actually the internal_id of the + # instance, not the value of the id column in the DB. + self.compute_api.update_instance(ctxt, instance.id, **update_dict) except exception.NotFound: return faults.Fault(exc.HTTPNotFound()) return exc.HTTPNoContent() -- cgit From 7c01430020ceabec765f388b70685808064cda3f Mon Sep 17 00:00:00 2001 From: Anthony Young Date: Tue, 4 Jan 2011 16:22:47 -0800 Subject: some more cleanup --- nova/api/ec2/admin.py | 1 - nova/api/ec2/cloud.py | 2 -- 2 files changed, 3 deletions(-) (limited to 'nova/api') diff --git a/nova/api/ec2/admin.py b/nova/api/ec2/admin.py index e876724b1..fac01369e 100644 --- a/nova/api/ec2/admin.py +++ b/nova/api/ec2/admin.py @@ -183,4 +183,3 @@ class AdminController(object): def describe_host(self, _context, name, **_kwargs): """Returns status info for single node.""" return host_dict(db.host_get(name)) - diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index 20413e319..a59131ab5 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -774,8 +774,6 @@ class CloudController(object): return self._format_run_instances(context, instances[0]['reservation_id']) - def run_instances2(self, context, **kwargs): - return self.run_instances(context, kwargs) def terminate_instances(self, context, instance_id, **kwargs): """Terminate each instance in instance_id, which is a list of ec2 ids. instance_id is a kwarg so its name cannot be modified.""" -- cgit From e774f2cd7206b5ae632a42c1eda7330858b1613c Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Wed, 5 Jan 2011 03:51:21 -0400 Subject: pep8 --- nova/api/openstack/common.py | 4 ++-- nova/api/openstack/images.py | 2 +- nova/api/openstack/servers.py | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'nova/api') diff --git a/nova/api/openstack/common.py b/nova/api/openstack/common.py index e2c7ed7ba..037ed47a0 100644 --- a/nova/api/openstack/common.py +++ b/nova/api/openstack/common.py @@ -47,8 +47,8 @@ def get_image_id_from_image_hash(image_service, context, image_hash): """ # FIX(sandy): This is terribly inefficient. It pulls all images - # from objectstore in order to find the match. ObjectStore - # should have a numeric counterpart to the string ID. + # from objectstore in order to find the match. ObjectStore + # should have a numeric counterpart to the string ID. try: items = image_service.detail(context) except NotImplementedError: diff --git a/nova/api/openstack/images.py b/nova/api/openstack/images.py index 4da3b943b..42ffd22a5 100644 --- a/nova/api/openstack/images.py +++ b/nova/api/openstack/images.py @@ -124,7 +124,7 @@ class Controller(wsgi.Controller): items = self._service.index(req.environ['nova.context']) for image in items: _convert_image_id_to_hash(image) - + items = common.limited(items, req) items = [_translate_keys(item) for item in items] items = [_translate_status(item) for item in items] diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index a5de62230..024de0072 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -132,11 +132,11 @@ class Controller(wsgi.Controller): with open(mapping_filename) as f: mapping = json.load(f) - if mapping.has_key(image_id): + if image_id in mapping: return mapping[image_id] raise exception.NotFound( - _("No entry for image '%s' in mapping file '%s'") % + _("No entry for image '%s' in mapping file '%s'") % (image_id, mapping_filename)) def create(self, req): @@ -154,8 +154,8 @@ class Controller(wsgi.Controller): req.environ['nova.context'], instance_types.get_by_flavor_id(env['server']['flavorId']), image_id, - kernel_id = kernel_id, - ramdisk_id = ramdisk_id, + kernel_id=kernel_id, + ramdisk_id=ramdisk_id, display_name=env['server']['name'], description=env['server']['name'], key_name=key_pair['name'], -- cgit From 8434ba0b13cc1b7e46be64ace3bee300de882aa0 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Wed, 5 Jan 2011 09:23:19 -0400 Subject: Changed Paused power state from Error to Paused --- nova/api/openstack/servers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/api') diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index 024de0072..52f93a3d2 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -50,7 +50,7 @@ def _translate_detail_keys(inst): power_state.RUNNING: 'active', power_state.BLOCKED: 'active', power_state.SUSPENDED: 'suspended', - power_state.PAUSED: 'error', + power_state.PAUSED: 'paused', power_state.SHUTDOWN: 'active', power_state.SHUTOFF: 'active', power_state.CRASHED: 'error'} -- cgit From 457e19826cfdb7f8f324180e42d8df79da48cfc6 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Thu, 6 Jan 2011 04:55:16 -0400 Subject: renamed sharedipgroups to shared_ip_groups and fixed tests for display_name --- nova/api/openstack/__init__.py | 4 +- nova/api/openstack/shared_ip_groups.py | 69 ++++++++++++++++++++++++++++++++++ nova/api/openstack/sharedipgroups.py | 69 ---------------------------------- 3 files changed, 71 insertions(+), 71 deletions(-) create mode 100644 nova/api/openstack/shared_ip_groups.py delete mode 100644 nova/api/openstack/sharedipgroups.py (limited to 'nova/api') diff --git a/nova/api/openstack/__init__.py b/nova/api/openstack/__init__.py index 0b54c7233..33eac001a 100644 --- a/nova/api/openstack/__init__.py +++ b/nova/api/openstack/__init__.py @@ -39,7 +39,7 @@ from nova.api.openstack import flavors from nova.api.openstack import images from nova.api.openstack import ratelimiting from nova.api.openstack import servers -from nova.api.openstack import sharedipgroups +from nova.api.openstack import shared_ip_groups FLAGS = flags.FLAGS @@ -114,7 +114,7 @@ class APIRouter(wsgi.Router): mapper.resource("flavor", "flavors", controller=flavors.Controller(), collection={'detail': 'GET'}) mapper.resource("shared_ip_group", "shared_ip_groups", - controller=sharedipgroups.Controller()) + controller=shared_ip_groups.Controller()) super(APIRouter, self).__init__(mapper) diff --git a/nova/api/openstack/shared_ip_groups.py b/nova/api/openstack/shared_ip_groups.py new file mode 100644 index 000000000..65595c8ff --- /dev/null +++ b/nova/api/openstack/shared_ip_groups.py @@ -0,0 +1,69 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2010 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. + +import logging + +from webob import exc + +from nova import wsgi +from nova.api.openstack import faults + + +def _translate_keys(inst): + """ Coerces a shared IP group instance into proper dictionary format """ + return dict(sharedIpGroup=inst) + + +def _translate_detail_keys(inst): + """ Coerces a shared IP group instance into proper dictionary format with + correctly mapped attributes """ + return dict(sharedIpGroups=inst) + + +class Controller(wsgi.Controller): + """ The Shared IP Groups Controller for the Openstack API """ + + _serialization_metadata = { + 'application/xml': { + 'attributes': { + 'sharedIpGroup': []}}} + + def index(self, req): + """ Returns a list of Shared IP Groups for the user """ + return dict(sharedIpGroups=[]) + + def show(self, req, id): + """ Shows in-depth information on a specific Shared IP Group """ + if id == 'detail': + return _translate_detail_keys({}) + return _translate_keys({}) + + def update(self, req, id): + """ You can't update a Shared IP Group """ + raise faults.Fault(exc.HTTPNotImplemented()) + + def delete(self, req, id): + """ Deletes a Shared IP Group """ + raise faults.Fault(exc.HTTPNotImplemented()) + + def detail(self, req, id): + """ Returns a complete list of Shared IP Groups """ + return _translate_detail_keys({}) + + def create(self, req): + """ Creates a new Shared IP group """ + raise faults.Fault(exc.HTTPNotImplemented()) diff --git a/nova/api/openstack/sharedipgroups.py b/nova/api/openstack/sharedipgroups.py deleted file mode 100644 index 65595c8ff..000000000 --- a/nova/api/openstack/sharedipgroups.py +++ /dev/null @@ -1,69 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010 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. - -import logging - -from webob import exc - -from nova import wsgi -from nova.api.openstack import faults - - -def _translate_keys(inst): - """ Coerces a shared IP group instance into proper dictionary format """ - return dict(sharedIpGroup=inst) - - -def _translate_detail_keys(inst): - """ Coerces a shared IP group instance into proper dictionary format with - correctly mapped attributes """ - return dict(sharedIpGroups=inst) - - -class Controller(wsgi.Controller): - """ The Shared IP Groups Controller for the Openstack API """ - - _serialization_metadata = { - 'application/xml': { - 'attributes': { - 'sharedIpGroup': []}}} - - def index(self, req): - """ Returns a list of Shared IP Groups for the user """ - return dict(sharedIpGroups=[]) - - def show(self, req, id): - """ Shows in-depth information on a specific Shared IP Group """ - if id == 'detail': - return _translate_detail_keys({}) - return _translate_keys({}) - - def update(self, req, id): - """ You can't update a Shared IP Group """ - raise faults.Fault(exc.HTTPNotImplemented()) - - def delete(self, req, id): - """ Deletes a Shared IP Group """ - raise faults.Fault(exc.HTTPNotImplemented()) - - def detail(self, req, id): - """ Returns a complete list of Shared IP Groups """ - return _translate_detail_keys({}) - - def create(self, req): - """ Creates a new Shared IP group """ - raise faults.Fault(exc.HTTPNotImplemented()) -- cgit From 3478e90442ad7a22497b53153ae893df96e55b4e Mon Sep 17 00:00:00 2001 From: Eldar Nugaev Date: Fri, 7 Jan 2011 05:59:30 +0300 Subject: merge --- nova/api/ec2/cloud.py | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) (limited to 'nova/api') diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index 6619b5452..b6966e605 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -140,6 +140,12 @@ class CloudController(object): {"method": "refresh_security_group", "args": {"security_group_id": security_group.id}}) + def _get_availability_zone_by_host(self, context, host): + services = db.service_get_all_by_host(context, host) + if len(services) > 0: + return services[0]['availability_zone'] + return 'unknown zone' + def get_metadata(self, address): ctxt = context.get_admin_context() instance_ref = self.compute_api.get_all(ctxt, fixed_ip=address) @@ -152,6 +158,8 @@ class CloudController(object): else: keys = '' hostname = instance_ref['hostname'] + availability_zone = self._get_availability_zone_by_host(ctxt, + instance_ref['host']) floating_ip = db.instance_get_floating_address(ctxt, instance_ref['id']) ec2_id = id_to_ec2_id(instance_ref['id']) @@ -174,8 +182,7 @@ class CloudController(object): 'local-hostname': hostname, 'local-ipv4': address, 'kernel-id': instance_ref['kernel_id'], - # TODO(vish): real zone - 'placement': {'availability-zone': 'nova'}, + 'placement': {'availability-zone': availability_zone}, 'public-hostname': hostname, 'public-ipv4': floating_ip or '', 'public-keys': keys, @@ -199,8 +206,25 @@ class CloudController(object): return self._describe_availability_zones(context, **kwargs) def _describe_availability_zones(self, context, **kwargs): - return {'availabilityZoneInfo': [{'zoneName': 'nova', - 'zoneState': 'available'}]} + enabled_services = db.service_get_all(context) + disabled_services = db.service_get_all(context, True) + available_zones = [] + for zone in [service.availability_zone for service in enabled_services]: + if not zone in available_zones: + available_zones.append(zone) + not_available_zones = [] + for zone in [service.availability_zone for service in disabled_services + and not service['availability_zone'] in available_zones]: + if not zone in not_available_zones: + not_available_zones.append(zone) + result = [] + for zone in available_zones: + result.append({'zoneName': zone, + 'zoneState': "available"}) + for zone in not_available_zones: + result.append({'zoneName': zone, + 'zoneState': "not available"}) + return {'availabilityZoneInfo': result} def _describe_availability_zones_verbose(self, context, **kwargs): rv = {'availabilityZoneInfo': [{'zoneName': 'nova', @@ -632,6 +656,8 @@ class CloudController(object): i['amiLaunchIndex'] = instance['launch_index'] i['displayName'] = instance['display_name'] i['displayDescription'] = instance['display_description'] + availability_zone = self._get_availability_zone_by_host(context, instance['host']) + i['placement'] = {'availabilityZone': availability_zone} if instance['reservation_id'] not in reservations: r = {} r['reservationId'] = instance['reservation_id'] -- cgit From 4edfa8ea26f8e820674e8bebbe34b6ed5885a69b Mon Sep 17 00:00:00 2001 From: Anthony Young Date: Mon, 10 Jan 2011 13:44:45 -0800 Subject: consolidate boto_extensions.py and euca-get-ajax-console, fix bugs from previous trunk merge --- nova/api/ec2/cloud.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/api') diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index 17b9a14fb..b426710bc 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -500,7 +500,7 @@ class CloudController(object): def get_ajax_console(self, context, instance_id, **kwargs): ec2_id = instance_id[0] - internal_id = ec2_id_to_internal_id(ec2_id) + internal_id = ec2_id_to_id(ec2_id) return self.compute_api.get_ajax_console(context, internal_id) def describe_volumes(self, context, volume_id=None, **kwargs): -- cgit From 77e75fefc7c9c4085a64eabb5ef44ffd5fff3229 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Tue, 11 Jan 2011 03:38:40 -0400 Subject: Changed shared_ip_group detail routing --- nova/api/openstack/shared_ip_groups.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'nova/api') diff --git a/nova/api/openstack/shared_ip_groups.py b/nova/api/openstack/shared_ip_groups.py index ec399db93..bd3cc23a8 100644 --- a/nova/api/openstack/shared_ip_groups.py +++ b/nova/api/openstack/shared_ip_groups.py @@ -48,8 +48,6 @@ class Controller(wsgi.Controller): def show(self, req, id): """ Shows in-depth information on a specific Shared IP Group """ - #if id == 'detail': - # return _translate_detail_keys({}) return _translate_keys({}) def update(self, req, id): @@ -60,7 +58,7 @@ class Controller(wsgi.Controller): """ Deletes a Shared IP Group """ raise faults.Fault(exc.HTTPNotImplemented()) - def detail(self, req, id): + def detail(self, req): """ Returns a complete list of Shared IP Groups """ return _translate_detail_keys({}) -- cgit From d01b546ae574f74b9c4c07a039c2c52cf0ed3bfb Mon Sep 17 00:00:00 2001 From: Eldar Nugaev Date: Wed, 12 Jan 2011 01:27:36 +0300 Subject: resolve pylint warnings --- nova/api/ec2/cloud.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'nova/api') diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index b6748e608..42245fa54 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -159,8 +159,8 @@ class CloudController(object): else: keys = '' hostname = instance_ref['hostname'] - availability_zone = self._get_availability_zone_by_host(ctxt, - instance_ref['host']) + host = instance_ref['host'] + availability_zone = self._get_availability_zone_by_host(ctxt, host) floating_ip = db.instance_get_floating_address(ctxt, instance_ref['id']) ec2_id = id_to_ec2_id(instance_ref['id']) @@ -210,12 +210,13 @@ class CloudController(object): enabled_services = db.service_get_all(context) disabled_services = db.service_get_all(context, True) available_zones = [] - for zone in [service.availability_zone for service in enabled_services]: + for zone in [service.availability_zone for service + in enabled_services]: if not zone in available_zones: available_zones.append(zone) not_available_zones = [] for zone in [service.availability_zone for service in disabled_services - and not service['availability_zone'] in available_zones]: + if not service['availability_zone'] in available_zones]: if not zone in not_available_zones: not_available_zones.append(zone) result = [] @@ -679,8 +680,9 @@ class CloudController(object): i['amiLaunchIndex'] = instance['launch_index'] i['displayName'] = instance['display_name'] i['displayDescription'] = instance['display_description'] - availability_zone = self._get_availability_zone_by_host(context, instance['host']) - i['placement'] = {'availabilityZone': availability_zone} + host = instance['host'] + zone = self._get_availability_zone_by_host(context, host) + i['placement'] = {'availabilityZone': zone} if instance['reservation_id'] not in reservations: r = {} r['reservationId'] = instance['reservation_id'] -- cgit From 0ac0cd5976ad6b053aa011071194614ee4f70c48 Mon Sep 17 00:00:00 2001 From: Todd Willey Date: Tue, 11 Jan 2011 18:03:15 -0500 Subject: Raise meaningful exception when there aren't enough params for a sec group rule. --- nova/api/ec2/cloud.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'nova/api') diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index 99a9677c4..135836348 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -399,8 +399,8 @@ class CloudController(object): criteria = self._revoke_rule_args_to_dict(context, **kwargs) if criteria == None: - raise exception.ApiError(_("No rule for the specified " - "parameters.")) + raise exception.ApiError(_("Not enough parameters to build a " + "valid rule.")) for rule in security_group.rules: match = True @@ -427,6 +427,9 @@ class CloudController(object): group_name) values = self._revoke_rule_args_to_dict(context, **kwargs) + if values is None: + raise exception.ApiError(_("Not enough parameters to build a " + "valid rule.")) values['parent_group_id'] = security_group.id if self._security_group_rule_exists(security_group, values): -- cgit