From 4ff2da231d485598232d9aacc41538950005ac34 Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Wed, 22 Dec 2010 16:43:47 -0800 Subject: Basic Easy API functionality --- nova/api/easy.py | 163 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 nova/api/easy.py (limited to 'nova/api') diff --git a/nova/api/easy.py b/nova/api/easy.py new file mode 100644 index 000000000..a284e9685 --- /dev/null +++ b/nova/api/easy.py @@ -0,0 +1,163 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2010 United States Government as represented by the +# Administrator of the National Aeronautics and Space Administration. +# 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. + +"""Public HTTP interface that allows services to self-register. + +The general flow of a request is: + - Request is parsed into WSGI bits. + - Some middleware checks authentication. + - Routing takes place based on the URL to find a controller. + (/controller/method) + - Parameters are parsed from the request and passed to a method on the + controller as keyword arguments. + - Optionally json_body is decoded to provide all the parameters. + - Actual work is done and a result is returned. + - That result is turned into json and returned. + +""" + +import json +import urllib + +import routes +import webob + +from nova import context +from nova import flags +from nova import wsgi + +# prxy compute_api in amazon tests + + +EASY_ROUTES = {} + + +def register_service(path, handle): + EASY_ROUTES[path] = handle + + +class DelegatedAuthMiddleware(wsgi.Middleware): + def process_request(self, request): + os_user = request.headers['X-OpenStack-User'] + os_project = request.headers['X-OpenStack-Project'] + context_ref = context.RequestContext(user=os_user, project=os_project) + request.environ['openstack.context'] = context_ref + + +class JsonParamsMiddleware(wsgi.Middleware): + def process_request(self, request): + if 'json' not in request.params: + return + + params_json = request.params['json'] + params_parsed = json.loads(params_json) + params = {} + for k, v in params_parsed.iteritems(): + if k in ('self', 'context'): + continue + if k.startswith('_'): + continue + params[k] = v + + request.environ['openstack.params'] = params + + +class ReqParamsMiddleware(wsgi.Middleware): + def process_request(self, request): + params_parsed = request.params + params = {} + for k, v in params_parsed.iteritems(): + if k in ('self', 'context'): + continue + if k.startswith('_'): + continue + params[k] = v + + request.environ['openstack.params'] = params + + +class SundayMorning(wsgi.Router): + def __init__(self, mapper=None): + if mapper is None: + mapper = routes.Mapper() + + self._load_registered_routes(mapper) + super(SundayMorning, self).__init__(mapper=mapper) + + def _load_registered_routes(self, mapper): + for route in EASY_ROUTES: + mapper.connect('/%s/{action}' % route, + controller=ServiceWrapper(EASY_ROUTES[route])) + + +class ServiceWrapper(wsgi.Controller): + def __init__(self, service_handle): + self.service_handle = service_handle + + @webob.dec.wsgify + def __call__(self, req): + arg_dict = req.environ['wsgiorg.routing_args'][1] + action = arg_dict['action'] + del arg_dict['action'] + + context = req.environ['openstack.context'] + # allow middleware up the stack to override the params + params = {} + if 'openstack.params' in req.environ: + params = req.environ['openstack.params'] + + # TODO(termie): do some basic normalization on methods + method = getattr(self.service_handle, action) + + result = method(context, **params) + if type(result) is dict: + return self._serialize(result, req) + else: + return result + + +class Proxy(object): + """Pretend an Easy API endpoint is an object.""" + def __init__(self, app, prefix=None): + self.app = app + self.prefix = prefix + + def __do_request(self, path, context, **kwargs): + req = webob.Request.blank(path) + req.method = 'POST' + req.body = urllib.urlencode({'json': json.dumps(kwargs)}) + req.environ['openstack.context'] = context + resp = req.get_response(self.app) + try: + return json.loads(resp.body) + except Exception: + return resp.body + + def __getattr__(self, key): + if self.prefix is None: + return self.__class__(self.app, key) + + def _wrapper(context, **kwargs): + return self.__do_request('/%s/%s' % (self.prefix, key), + context, + **kwargs) + _wrapper.func_name = key + return _wrapper + + + -- cgit From 70d254c626e925f6de8408f0ca70f3de28a7307a Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Wed, 22 Dec 2010 17:53:42 -0800 Subject: added tests to ensure the easy api works as a backend for Compute API --- nova/api/easy.py | 10 +++++----- nova/api/ec2/cloud.py | 34 ++++++++++++++++++++-------------- 2 files changed, 25 insertions(+), 19 deletions(-) (limited to 'nova/api') diff --git a/nova/api/easy.py b/nova/api/easy.py index a284e9685..9ef487739 100644 --- a/nova/api/easy.py +++ b/nova/api/easy.py @@ -31,7 +31,6 @@ The general flow of a request is: """ -import json import urllib import routes @@ -39,6 +38,7 @@ import webob from nova import context from nova import flags +from nova import utils from nova import wsgi # prxy compute_api in amazon tests @@ -65,7 +65,7 @@ class JsonParamsMiddleware(wsgi.Middleware): return params_json = request.params['json'] - params_parsed = json.loads(params_json) + params_parsed = utils.loads(params_json) params = {} for k, v in params_parsed.iteritems(): if k in ('self', 'context'): @@ -125,7 +125,7 @@ class ServiceWrapper(wsgi.Controller): method = getattr(self.service_handle, action) result = method(context, **params) - if type(result) is dict: + if type(result) is dict or type(result) is list: return self._serialize(result, req) else: return result @@ -140,11 +140,11 @@ class Proxy(object): def __do_request(self, path, context, **kwargs): req = webob.Request.blank(path) req.method = 'POST' - req.body = urllib.urlencode({'json': json.dumps(kwargs)}) + req.body = urllib.urlencode({'json': utils.dumps(kwargs)}) req.environ['openstack.context'] = context resp = req.get_response(self.app) try: - return json.loads(resp.body) + return utils.loads(resp.body) except Exception: return resp.body diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index e09261f00..61c6c0da1 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -118,7 +118,8 @@ class CloudController(object): def _get_mpi_data(self, context, project_id): result = {} - for instance in self.compute_api.get_instances(context, project_id): + for instance in self.compute_api.get_instances(context, + project_id=project_id): if instance['fixed_ip']: line = '%s slots=%d' % (instance['fixed_ip']['address'], instance['vcpus']) @@ -442,7 +443,8 @@ class CloudController(object): # 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 = self.compute_api.get_instance(context, internal_id) + instance_ref = self.compute_api.get_instance(context, + instance_id=internal_id) output = rpc.call(context, '%s.%s' % (FLAGS.compute_topic, instance_ref['host']), @@ -541,7 +543,8 @@ class CloudController(object): if volume_ref['attach_status'] == "attached": raise exception.ApiError(_("Volume is already attached")) internal_id = ec2_id_to_internal_id(instance_id) - instance_ref = self.compute_api.get_instance(context, internal_id) + instance_ref = self.compute_api.get_instance(context, + instance_id=internal_id) host = instance_ref['host'] rpc.cast(context, db.queue_get_for(context, FLAGS.compute_topic, host), @@ -722,14 +725,15 @@ class CloudController(object): def associate_address(self, context, instance_id, public_ip, **kwargs): internal_id = ec2_id_to_internal_id(instance_id) - instance_ref = self.compute_api.get_instance(context, internal_id) + instance_ref = self.compute_api.get_instance(context, + instance_id=internal_id) fixed_address = db.instance_get_fixed_address(context, instance_ref['id']) floating_ip_ref = db.floating_ip_get_by_address(context, public_ip) # NOTE(vish): Perhaps we should just pass this on to compute and # let compute communicate with network. - network_topic = self.compute_api.get_network_topic(context, - internal_id) + network_topic = self.compute_api.get_network_topic( + context, instance_id=internal_id) rpc.cast(context, network_topic, {"method": "associate_floating_ip", @@ -754,8 +758,9 @@ class CloudController(object): def run_instances(self, context, **kwargs): max_count = int(kwargs.get('max_count', 1)) instances = self.compute_api.create_instances(context, - instance_types.get_by_type(kwargs.get('instance_type', None)), - kwargs['image_id'], + instance_type=instance_types.get_by_type( + kwargs.get('instance_type', None)), + image_id=kwargs['image_id'], min_count=int(kwargs.get('min_count', max_count)), max_count=max_count, kernel_id=kwargs.get('kernel_id', None), @@ -765,7 +770,7 @@ class CloudController(object): key_name=kwargs.get('key_name'), user_data=kwargs.get('user_data'), security_group=kwargs.get('security_group'), - generate_hostname=internal_id_to_ec2_id) + hostname_format='ec2') return self._format_run_instances(context, instances[0]['reservation_id']) @@ -775,26 +780,26 @@ class CloudController(object): logging.debug("Going to start terminating instances") for ec2_id in instance_id: internal_id = ec2_id_to_internal_id(ec2_id) - self.compute_api.delete_instance(context, internal_id) + self.compute_api.delete_instance(context, instance_id=internal_id) return True def reboot_instances(self, context, instance_id, **kwargs): """instance_id is a list of instance ids""" for ec2_id in instance_id: internal_id = ec2_id_to_internal_id(ec2_id) - self.compute_api.reboot(context, internal_id) + self.compute_api.reboot(context, instance_id=internal_id) return True def rescue_instance(self, context, instance_id, **kwargs): """This is an extension to the normal ec2_api""" internal_id = ec2_id_to_internal_id(instance_id) - self.compute_api.rescue(context, internal_id) + self.compute_api.rescue(context, instance_id=internal_id) return True def unrescue_instance(self, context, instance_id, **kwargs): """This is an extension to the normal ec2_api""" internal_id = ec2_id_to_internal_id(instance_id) - self.compute_api.unrescue(context, internal_id) + self.compute_api.unrescue(context, instance_id=internal_id) return True def update_instance(self, context, ec2_id, **kwargs): @@ -805,7 +810,8 @@ class CloudController(object): changes[field] = kwargs[field] if changes: internal_id = ec2_id_to_internal_id(ec2_id) - inst = self.compute_api.get_instance(context, internal_id) + inst = self.compute_api.get_instance(context, + instance_id=internal_id) db.instance_update(context, inst['id'], kwargs) return True -- cgit From 7c1b3ef521c652ce375390a1ecb04a60d1f100f0 Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Wed, 22 Dec 2010 18:04:35 -0800 Subject: remove some notes --- nova/api/easy.py | 2 -- 1 file changed, 2 deletions(-) (limited to 'nova/api') diff --git a/nova/api/easy.py b/nova/api/easy.py index 9ef487739..1be52069f 100644 --- a/nova/api/easy.py +++ b/nova/api/easy.py @@ -41,8 +41,6 @@ from nova import flags from nova import utils from nova import wsgi -# prxy compute_api in amazon tests - EASY_ROUTES = {} -- cgit From a1b5220879632d093f450413f96668a8f77c0613 Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Thu, 23 Dec 2010 12:04:19 -0800 Subject: adds a reflection api --- nova/api/easy.py | 52 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 4 deletions(-) (limited to 'nova/api') diff --git a/nova/api/easy.py b/nova/api/easy.py index 1be52069f..0e4f8a892 100644 --- a/nova/api/easy.py +++ b/nova/api/easy.py @@ -31,6 +31,7 @@ The general flow of a request is: """ +import inspect import urllib import routes @@ -102,6 +103,52 @@ class SundayMorning(wsgi.Router): mapper.connect('/%s/{action}' % route, controller=ServiceWrapper(EASY_ROUTES[route])) + +class Reflection(object): + def __init__(self): + self._methods = {} + + def _gather_methods(self): + methods = {} + for route, handler in EASY_ROUTES.iteritems(): + for k in dir(handler): + if k.startswith('_'): + continue + f = getattr(handler, k) + if not callable(f): + continue + + # bunch of ugly formatting stuff + argspec = inspect.getargspec(f) + args = [x for x in argspec[0] if x != 'self' and x != 'context'] + defaults = argspec[3] and argspec[3] or [] + args_r = list(reversed(args)) + defaults_r = list(reversed(defaults)) + args_out = [] + while args_r: + if defaults_r: + args_out.append((args_r.pop(0), defaults_r.pop(0))) + else: + args_out.append(str(args_r.pop(0))) + + methods['/%s/%s' % (route, k)] = { + 'name': k, + 'args': list(reversed(args_out))} + return methods + + def get_methods(self, context): + if not self._methods: + self._methods = self._gather_methods() + + method_list = self._methods.keys() + method_list.sort() + return {'methods': method_list} + + def get_method_info(self, context, method): + if not self._methods: + self._methods = self._gather_methods() + return self._methods[method] + class ServiceWrapper(wsgi.Controller): def __init__(self, service_handle): @@ -148,7 +195,7 @@ class Proxy(object): def __getattr__(self, key): if self.prefix is None: - return self.__class__(self.app, key) + return self.__class__(self.app, prefix=key) def _wrapper(context, **kwargs): return self.__do_request('/%s/%s' % (self.prefix, key), @@ -156,6 +203,3 @@ class Proxy(object): **kwargs) _wrapper.func_name = key return _wrapper - - - -- cgit From c5c58cb20def79401a374f863983a343139b53f3 Mon Sep 17 00:00:00 2001 From: "NTT PF Lab." Date: Fri, 24 Dec 2010 20:38:49 +0900 Subject: Support IPv6 --- nova/api/ec2/cloud.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'nova/api') diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index ebb13aedc..ff7a2f3cd 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -31,7 +31,7 @@ import time from nova import context import IPy - +import urllib from nova import crypto from nova import db from nova import exception @@ -307,6 +307,7 @@ class CloudController(object): values['group_id'] = source_security_group['id'] elif cidr_ip: # If this fails, it throws an exception. This is what we want. + cidr_ip = urllib.unquote(cidr_ip).decode() IPy.IP(cidr_ip) values['cidr'] = cidr_ip else: @@ -635,10 +636,16 @@ class CloudController(object): if instance['fixed_ip']['floating_ips']: fixed = instance['fixed_ip'] floating_addr = fixed['floating_ips'][0]['address'] + if instance['fixed_ip']['network'] and FLAGS.use_ipv6: + i['dnsNameV6'] = utils.to_global_ipv6( + instance['fixed_ip']['network']['cidr_v6'], + instance['mac_address']) + i['privateDnsName'] = fixed_addr i['publicDnsName'] = floating_addr i['dnsName'] = i['publicDnsName'] or i['privateDnsName'] i['keyName'] = instance['key_name'] + if context.user.is_admin(): i['keyName'] = '%s (%s, %s)' % (i['keyName'], instance['project_id'], -- cgit From 8e1b74aa1c5a2f9113473eedc8e35b38b41445ea Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Mon, 27 Dec 2010 15:15:24 -0800 Subject: Added stack command-line tool --- nova/api/easy.py | 57 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 15 deletions(-) (limited to 'nova/api') diff --git a/nova/api/easy.py b/nova/api/easy.py index 0e4f8a892..7468e3115 100644 --- a/nova/api/easy.py +++ b/nova/api/easy.py @@ -25,7 +25,7 @@ The general flow of a request is: (/controller/method) - Parameters are parsed from the request and passed to a method on the controller as keyword arguments. - - Optionally json_body is decoded to provide all the parameters. + - Optionally 'json' is decoded to provide all the parameters. - Actual work is done and a result is returned. - That result is turned into json and returned. @@ -94,7 +94,7 @@ class SundayMorning(wsgi.Router): def __init__(self, mapper=None): if mapper is None: mapper = routes.Mapper() - + self._load_registered_routes(mapper) super(SundayMorning, self).__init__(mapper=mapper) @@ -103,14 +103,18 @@ class SundayMorning(wsgi.Router): mapper.connect('/%s/{action}' % route, controller=ServiceWrapper(EASY_ROUTES[route])) - + class Reflection(object): + """Reflection methods to list available methods.""" def __init__(self): self._methods = {} + self._controllers = {} def _gather_methods(self): methods = {} + controllers = {} for route, handler in EASY_ROUTES.iteritems(): + controllers[route] = handler.__doc__.split('\n')[0] for k in dir(handler): if k.startswith('_'): continue @@ -120,40 +124,63 @@ class Reflection(object): # bunch of ugly formatting stuff argspec = inspect.getargspec(f) - args = [x for x in argspec[0] if x != 'self' and x != 'context'] + args = [x for x in argspec[0] + if x != 'self' and x != 'context'] defaults = argspec[3] and argspec[3] or [] args_r = list(reversed(args)) defaults_r = list(reversed(defaults)) + args_out = [] while args_r: if defaults_r: - args_out.append((args_r.pop(0), defaults_r.pop(0))) + args_out.append((args_r.pop(0), + repr(defaults_r.pop(0)))) else: - args_out.append(str(args_r.pop(0))) + args_out.append((str(args_r.pop(0)),)) + + # if the method accepts keywords + if argspec[2]: + args_out.insert(0, ('**%s' % argspec[2],)) methods['/%s/%s' % (route, k)] = { + 'short_doc': f.__doc__.split('\n')[0], + 'doc': f.__doc__, 'name': k, 'args': list(reversed(args_out))} - return methods + + self._methods = methods + self._controllers = controllers + + def get_controllers(self, context): + """List available controllers.""" + if not self._controllers: + self._gather_methods() + + return self._controllers def get_methods(self, context): + """List available methods.""" if not self._methods: - self._methods = self._gather_methods() + self._gather_methods() method_list = self._methods.keys() method_list.sort() - return {'methods': method_list} + methods = {} + for k in method_list: + methods[k] = self._methods[k]['short_doc'] + return methods def get_method_info(self, context, method): + """Get detailed information about a method.""" if not self._methods: - self._methods = self._gather_methods() + self._gather_methods() return self._methods[method] class ServiceWrapper(wsgi.Controller): def __init__(self, service_handle): self.service_handle = service_handle - + @webob.dec.wsgify def __call__(self, req): arg_dict = req.environ['wsgiorg.routing_args'][1] @@ -165,10 +192,10 @@ class ServiceWrapper(wsgi.Controller): params = {} if 'openstack.params' in req.environ: params = req.environ['openstack.params'] - + # TODO(termie): do some basic normalization on methods method = getattr(self.service_handle, action) - + result = method(context, **params) if type(result) is dict or type(result) is list: return self._serialize(result, req) @@ -181,7 +208,7 @@ class Proxy(object): def __init__(self, app, prefix=None): self.app = app self.prefix = prefix - + def __do_request(self, path, context, **kwargs): req = webob.Request.blank(path) req.method = 'POST' @@ -196,7 +223,7 @@ class Proxy(object): def __getattr__(self, key): if self.prefix is None: return self.__class__(self.app, prefix=key) - + def _wrapper(context, **kwargs): return self.__do_request('/%s/%s' % (self.prefix, key), context, -- cgit From 35d3050511ef513ff440fbd9f8b44695ea8be797 Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Tue, 4 Jan 2011 14:07:46 -0800 Subject: rename Easy API to Direct API --- nova/api/direct.py | 232 +++++++++++++++++++++++++++++++++++++++++++++++++++++ nova/api/easy.py | 232 ----------------------------------------------------- 2 files changed, 232 insertions(+), 232 deletions(-) create mode 100644 nova/api/direct.py delete mode 100644 nova/api/easy.py (limited to 'nova/api') diff --git a/nova/api/direct.py b/nova/api/direct.py new file mode 100644 index 000000000..81b3ae202 --- /dev/null +++ b/nova/api/direct.py @@ -0,0 +1,232 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2010 United States Government as represented by the +# Administrator of the National Aeronautics and Space Administration. +# 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. + +"""Public HTTP interface that allows services to self-register. + +The general flow of a request is: + - Request is parsed into WSGI bits. + - Some middleware checks authentication. + - Routing takes place based on the URL to find a controller. + (/controller/method) + - Parameters are parsed from the request and passed to a method on the + controller as keyword arguments. + - Optionally 'json' is decoded to provide all the parameters. + - Actual work is done and a result is returned. + - That result is turned into json and returned. + +""" + +import inspect +import urllib + +import routes +import webob + +from nova import context +from nova import flags +from nova import utils +from nova import wsgi + + +ROUTES = {} + + +def register_service(path, handle): + ROUTES[path] = handle + + +class Router(wsgi.Router): + def __init__(self, mapper=None): + if mapper is None: + mapper = routes.Mapper() + + self._load_registered_routes(mapper) + super(Router, self).__init__(mapper=mapper) + + def _load_registered_routes(self, mapper): + for route in ROUTES: + mapper.connect('/%s/{action}' % route, + controller=ServiceWrapper(ROUTES[route])) + + +class DelegatedAuthMiddleware(wsgi.Middleware): + def process_request(self, request): + os_user = request.headers['X-OpenStack-User'] + os_project = request.headers['X-OpenStack-Project'] + context_ref = context.RequestContext(user=os_user, project=os_project) + request.environ['openstack.context'] = context_ref + + +class JsonParamsMiddleware(wsgi.Middleware): + def process_request(self, request): + if 'json' not in request.params: + return + + params_json = request.params['json'] + params_parsed = utils.loads(params_json) + params = {} + for k, v in params_parsed.iteritems(): + if k in ('self', 'context'): + continue + if k.startswith('_'): + continue + params[k] = v + + request.environ['openstack.params'] = params + + +class PostParamsMiddleware(wsgi.Middleware): + def process_request(self, request): + params_parsed = request.params + params = {} + for k, v in params_parsed.iteritems(): + if k in ('self', 'context'): + continue + if k.startswith('_'): + continue + params[k] = v + + request.environ['openstack.params'] = params + + +class Reflection(object): + """Reflection methods to list available methods.""" + def __init__(self): + self._methods = {} + self._controllers = {} + + def _gather_methods(self): + methods = {} + controllers = {} + for route, handler in ROUTES.iteritems(): + controllers[route] = handler.__doc__.split('\n')[0] + for k in dir(handler): + if k.startswith('_'): + continue + f = getattr(handler, k) + if not callable(f): + continue + + # bunch of ugly formatting stuff + argspec = inspect.getargspec(f) + args = [x for x in argspec[0] + if x != 'self' and x != 'context'] + defaults = argspec[3] and argspec[3] or [] + args_r = list(reversed(args)) + defaults_r = list(reversed(defaults)) + + args_out = [] + while args_r: + if defaults_r: + args_out.append((args_r.pop(0), + repr(defaults_r.pop(0)))) + else: + args_out.append((str(args_r.pop(0)),)) + + # if the method accepts keywords + if argspec[2]: + args_out.insert(0, ('**%s' % argspec[2],)) + + methods['/%s/%s' % (route, k)] = { + 'short_doc': f.__doc__.split('\n')[0], + 'doc': f.__doc__, + 'name': k, + 'args': list(reversed(args_out))} + + self._methods = methods + self._controllers = controllers + + def get_controllers(self, context): + """List available controllers.""" + if not self._controllers: + self._gather_methods() + + return self._controllers + + def get_methods(self, context): + """List available methods.""" + if not self._methods: + self._gather_methods() + + method_list = self._methods.keys() + method_list.sort() + methods = {} + for k in method_list: + methods[k] = self._methods[k]['short_doc'] + return methods + + def get_method_info(self, context, method): + """Get detailed information about a method.""" + if not self._methods: + self._gather_methods() + return self._methods[method] + + +class ServiceWrapper(wsgi.Controller): + def __init__(self, service_handle): + self.service_handle = service_handle + + @webob.dec.wsgify + def __call__(self, req): + arg_dict = req.environ['wsgiorg.routing_args'][1] + action = arg_dict['action'] + del arg_dict['action'] + + context = req.environ['openstack.context'] + # allow middleware up the stack to override the params + params = {} + if 'openstack.params' in req.environ: + params = req.environ['openstack.params'] + + # TODO(termie): do some basic normalization on methods + method = getattr(self.service_handle, action) + + result = method(context, **params) + if type(result) is dict or type(result) is list: + return self._serialize(result, req) + else: + return result + + +class Proxy(object): + """Pretend a Direct API endpoint is an object.""" + def __init__(self, app, prefix=None): + self.app = app + self.prefix = prefix + + def __do_request(self, path, context, **kwargs): + req = webob.Request.blank(path) + req.method = 'POST' + req.body = urllib.urlencode({'json': utils.dumps(kwargs)}) + req.environ['openstack.context'] = context + resp = req.get_response(self.app) + try: + return utils.loads(resp.body) + except Exception: + return resp.body + + def __getattr__(self, key): + if self.prefix is None: + return self.__class__(self.app, prefix=key) + + def _wrapper(context, **kwargs): + return self.__do_request('/%s/%s' % (self.prefix, key), + context, + **kwargs) + _wrapper.func_name = key + return _wrapper diff --git a/nova/api/easy.py b/nova/api/easy.py deleted file mode 100644 index 7468e3115..000000000 --- a/nova/api/easy.py +++ /dev/null @@ -1,232 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# 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. - -"""Public HTTP interface that allows services to self-register. - -The general flow of a request is: - - Request is parsed into WSGI bits. - - Some middleware checks authentication. - - Routing takes place based on the URL to find a controller. - (/controller/method) - - Parameters are parsed from the request and passed to a method on the - controller as keyword arguments. - - Optionally 'json' is decoded to provide all the parameters. - - Actual work is done and a result is returned. - - That result is turned into json and returned. - -""" - -import inspect -import urllib - -import routes -import webob - -from nova import context -from nova import flags -from nova import utils -from nova import wsgi - - -EASY_ROUTES = {} - - -def register_service(path, handle): - EASY_ROUTES[path] = handle - - -class DelegatedAuthMiddleware(wsgi.Middleware): - def process_request(self, request): - os_user = request.headers['X-OpenStack-User'] - os_project = request.headers['X-OpenStack-Project'] - context_ref = context.RequestContext(user=os_user, project=os_project) - request.environ['openstack.context'] = context_ref - - -class JsonParamsMiddleware(wsgi.Middleware): - def process_request(self, request): - if 'json' not in request.params: - return - - params_json = request.params['json'] - params_parsed = utils.loads(params_json) - params = {} - for k, v in params_parsed.iteritems(): - if k in ('self', 'context'): - continue - if k.startswith('_'): - continue - params[k] = v - - request.environ['openstack.params'] = params - - -class ReqParamsMiddleware(wsgi.Middleware): - def process_request(self, request): - params_parsed = request.params - params = {} - for k, v in params_parsed.iteritems(): - if k in ('self', 'context'): - continue - if k.startswith('_'): - continue - params[k] = v - - request.environ['openstack.params'] = params - - -class SundayMorning(wsgi.Router): - def __init__(self, mapper=None): - if mapper is None: - mapper = routes.Mapper() - - self._load_registered_routes(mapper) - super(SundayMorning, self).__init__(mapper=mapper) - - def _load_registered_routes(self, mapper): - for route in EASY_ROUTES: - mapper.connect('/%s/{action}' % route, - controller=ServiceWrapper(EASY_ROUTES[route])) - - -class Reflection(object): - """Reflection methods to list available methods.""" - def __init__(self): - self._methods = {} - self._controllers = {} - - def _gather_methods(self): - methods = {} - controllers = {} - for route, handler in EASY_ROUTES.iteritems(): - controllers[route] = handler.__doc__.split('\n')[0] - for k in dir(handler): - if k.startswith('_'): - continue - f = getattr(handler, k) - if not callable(f): - continue - - # bunch of ugly formatting stuff - argspec = inspect.getargspec(f) - args = [x for x in argspec[0] - if x != 'self' and x != 'context'] - defaults = argspec[3] and argspec[3] or [] - args_r = list(reversed(args)) - defaults_r = list(reversed(defaults)) - - args_out = [] - while args_r: - if defaults_r: - args_out.append((args_r.pop(0), - repr(defaults_r.pop(0)))) - else: - args_out.append((str(args_r.pop(0)),)) - - # if the method accepts keywords - if argspec[2]: - args_out.insert(0, ('**%s' % argspec[2],)) - - methods['/%s/%s' % (route, k)] = { - 'short_doc': f.__doc__.split('\n')[0], - 'doc': f.__doc__, - 'name': k, - 'args': list(reversed(args_out))} - - self._methods = methods - self._controllers = controllers - - def get_controllers(self, context): - """List available controllers.""" - if not self._controllers: - self._gather_methods() - - return self._controllers - - def get_methods(self, context): - """List available methods.""" - if not self._methods: - self._gather_methods() - - method_list = self._methods.keys() - method_list.sort() - methods = {} - for k in method_list: - methods[k] = self._methods[k]['short_doc'] - return methods - - def get_method_info(self, context, method): - """Get detailed information about a method.""" - if not self._methods: - self._gather_methods() - return self._methods[method] - - -class ServiceWrapper(wsgi.Controller): - def __init__(self, service_handle): - self.service_handle = service_handle - - @webob.dec.wsgify - def __call__(self, req): - arg_dict = req.environ['wsgiorg.routing_args'][1] - action = arg_dict['action'] - del arg_dict['action'] - - context = req.environ['openstack.context'] - # allow middleware up the stack to override the params - params = {} - if 'openstack.params' in req.environ: - params = req.environ['openstack.params'] - - # TODO(termie): do some basic normalization on methods - method = getattr(self.service_handle, action) - - result = method(context, **params) - if type(result) is dict or type(result) is list: - return self._serialize(result, req) - else: - return result - - -class Proxy(object): - """Pretend an Easy API endpoint is an object.""" - def __init__(self, app, prefix=None): - self.app = app - self.prefix = prefix - - def __do_request(self, path, context, **kwargs): - req = webob.Request.blank(path) - req.method = 'POST' - req.body = urllib.urlencode({'json': utils.dumps(kwargs)}) - req.environ['openstack.context'] = context - resp = req.get_response(self.app) - try: - return utils.loads(resp.body) - except Exception: - return resp.body - - def __getattr__(self, key): - if self.prefix is None: - return self.__class__(self.app, prefix=key) - - def _wrapper(context, **kwargs): - return self.__do_request('/%s/%s' % (self.prefix, key), - context, - **kwargs) - _wrapper.func_name = key - return _wrapper -- cgit From f67802d62ee530b4e81aaf108dfd3813c84550b2 Mon Sep 17 00:00:00 2001 From: Ed Leafe Date: Wed, 5 Jan 2011 16:41:50 -0600 Subject: intermediate work --- nova/api/__init__.py | 14 ++++++++++++-- nova/api/openstack/servers.py | 7 ++++--- 2 files changed, 16 insertions(+), 5 deletions(-) (limited to 'nova/api') diff --git a/nova/api/__init__.py b/nova/api/__init__.py index 26fed847b..ff936bed2 100644 --- a/nova/api/__init__.py +++ b/nova/api/__init__.py @@ -59,13 +59,23 @@ 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) mapper.connect("/services/{path_info:.*}", controller=ec2.API(), conditions=ec2api_subdomain) + +# mapper.connect("/", controller=self.osapi_versions, +# conditions=osapi_subdomain) +# mapper.connect("/v1.0/{path_info:.*}", controller=openstack.API(), +# conditions=osapi_subdomain) +# +# mapper.connect("/", controller=self.ec2api_versions, +# conditions=ec2api_subdomain) +# mapper.connect("/services/{path_info:.*}", controller=ec2.API(), +# conditions=ec2api_subdomain) + mrh = metadatarequesthandler.MetadataRequestHandler() for s in ['/latest', '/2009-04-04', diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index c5cbe21ef..4bdb14d04 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -152,9 +152,10 @@ 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. + instance = self.compute_api.get_instance(ctxt, id) + self.compute_api.update_instance(ctxt, instance.id, **update_dict) except exception.NotFound: return faults.Fault(exc.HTTPNotFound()) return exc.HTTPNoContent() -- cgit From 3d70b49a1c17bccfc6163198b2d99efb9a9829a7 Mon Sep 17 00:00:00 2001 From: Ed Leafe Date: Thu, 6 Jan 2011 13:02:32 -0600 Subject: commit before merging trunk --- nova/api/ec2/cloud.py | 2 +- nova/api/openstack/servers.py | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) (limited to 'nova/api') diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index 0c0027287..6619b5452 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -592,7 +592,7 @@ class CloudController(object): return {'reservationSet': self._format_instances(context)} def _format_run_instances(self, context, reservation_id): - i = self._format_instances(context, reservation_id) + i = self._format_instances(context, reservation_id=reservation_id) assert len(i) == 1 return i[0] diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index 05ba56c79..e0513e4c1 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -104,7 +104,7 @@ class Controller(wsgi.Controller): def show(self, req, id): """ Returns server details by server id """ try: - instance = self.compute_api.get(req.environ['nova.context'], id) + instance = self.compute_api.get_instance(req.environ['nova.context'], id) return _translate_detail_keys(instance) except exception.NotFound: return faults.Fault(exc.HTTPNotFound()) @@ -142,8 +142,10 @@ class Controller(wsgi.Controller): return faults.Fault(exc.HTTPUnprocessableEntity()) update_dict = {} + func = None if 'adminPass' in inst_dict['server']: update_dict['admin_pass'] = inst_dict['server']['adminPass'] + func = self.compute_api.set_admin_password if 'name' in inst_dict['server']: update_dict['display_name'] = inst_dict['server']['name'] @@ -152,9 +154,15 @@ class Controller(wsgi.Controller): # The ID passed in is actually the internal_id of the # instance, not the value of the id column in the DB. instance = self.compute_api.get_instance(ctxt, id) - self.compute_api.update_instance(ctxt, instance.id, **update_dict) + self.compute_api.update(ctxt, instance.id, **update_dict) except exception.NotFound: return faults.Fault(exc.HTTPNotFound()) + + logging.error("ZZZZ func=%s" % func) + logging.error("ZZZZ UPD=%s" % id) + + if func: + func(ctxt, id) return exc.HTTPNoContent() def action(self, req, id): @@ -225,4 +233,4 @@ class Controller(wsgi.Controller): def actions(self, req, id): """Permit Admins to retrieve server actions.""" ctxt = req.environ["nova.context"] - return self.compute_api.get_actions(ctxt, id) + return self.compute_api.get_actions(ctxt, id_val) -- cgit From e66f3017373dcf9135c53ae4d510b0b2a5dcecf0 Mon Sep 17 00:00:00 2001 From: Ed Leafe Date: Thu, 6 Jan 2011 15:53:11 -0600 Subject: Got the basic 'set admin password' stuff working --- nova/api/openstack/servers.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'nova/api') diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index e0513e4c1..bc89f696c 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -104,7 +104,8 @@ class Controller(wsgi.Controller): def show(self, req, id): """ Returns server details by server id """ try: - instance = self.compute_api.get_instance(req.environ['nova.context'], id) + instance = self.compute_api.get_instance( + req.environ['nova.context'], id) return _translate_detail_keys(instance) except exception.NotFound: return faults.Fault(exc.HTTPNotFound()) @@ -141,6 +142,7 @@ class Controller(wsgi.Controller): if not inst_dict: return faults.Fault(exc.HTTPUnprocessableEntity()) + ctxt = req.environ['nova.context'] update_dict = {} func = None if 'adminPass' in inst_dict['server']: @@ -148,21 +150,18 @@ class Controller(wsgi.Controller): func = self.compute_api.set_admin_password if 'name' in inst_dict['server']: update_dict['display_name'] = inst_dict['server']['name'] - + if func: + try: + func(ctxt, id) + except exception.TimeoutException, e: + return exc.HTTPRequestTimeout() try: - ctxt = req.environ['nova.context'] # The ID passed in is actually the internal_id of the # instance, not the value of the id column in the DB. instance = self.compute_api.get_instance(ctxt, id) self.compute_api.update(ctxt, instance.id, **update_dict) except exception.NotFound: return faults.Fault(exc.HTTPNotFound()) - - logging.error("ZZZZ func=%s" % func) - logging.error("ZZZZ UPD=%s" % id) - - if func: - func(ctxt, id) return exc.HTTPNoContent() def action(self, req, id): -- cgit From dea9f51d65ce0d5c3c4ea328a2231499c71719d6 Mon Sep 17 00:00:00 2001 From: Ed Leafe Date: Thu, 6 Jan 2011 17:37:02 -0500 Subject: various cleanup and fixes --- nova/api/openstack/servers.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'nova/api') diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index bc89f696c..9eaef2b40 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -156,10 +156,7 @@ class Controller(wsgi.Controller): except exception.TimeoutException, e: return exc.HTTPRequestTimeout() try: - # The ID passed in is actually the internal_id of the - # instance, not the value of the id column in the DB. - instance = self.compute_api.get_instance(ctxt, id) - self.compute_api.update(ctxt, instance.id, **update_dict) + self.compute_api.update(ctxt, id, **update_dict) except exception.NotFound: return faults.Fault(exc.HTTPNotFound()) return exc.HTTPNoContent() @@ -232,4 +229,4 @@ class Controller(wsgi.Controller): def actions(self, req, id): """Permit Admins to retrieve server actions.""" ctxt = req.environ["nova.context"] - return self.compute_api.get_actions(ctxt, id_val) + return self.compute_api.get_actions(ctxt, id) -- cgit From eaa5b5994891eee0280b750dff221a4b54932eb9 Mon Sep 17 00:00:00 2001 From: Ed Leafe Date: Fri, 7 Jan 2011 10:23:48 -0600 Subject: getting ready to push for merge prop --- nova/api/openstack/servers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'nova/api') diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index a426a721d..280e2349e 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -104,7 +104,7 @@ class Controller(wsgi.Controller): def show(self, req, id): """ Returns server details by server id """ try: - instance = self.compute_api.get_instance( + instance = self.compute_api.get( req.environ['nova.context'], id) return _translate_detail_keys(instance) except exception.NotFound: @@ -158,7 +158,7 @@ class Controller(wsgi.Controller): try: # The ID passed in is actually the internal_id of the # instance, not the value of the id column in the DB. - instance = self.compute_api.get_instance(ctxt, id) + instance = self.compute_api.get(ctxt, id) self.compute_api.update(ctxt, instance.id, **update_dict) except exception.NotFound: return faults.Fault(exc.HTTPNotFound()) -- cgit From 147693e45c7be174c54e39160869ca9a83bb4fff Mon Sep 17 00:00:00 2001 From: Ed Leafe Date: Fri, 7 Jan 2011 11:04:53 -0600 Subject: Additional cleanup prior to pushing --- nova/api/__init__.py | 14 ++------------ nova/api/openstack/servers.py | 2 -- 2 files changed, 2 insertions(+), 14 deletions(-) (limited to 'nova/api') diff --git a/nova/api/__init__.py b/nova/api/__init__.py index ff936bed2..26fed847b 100644 --- a/nova/api/__init__.py +++ b/nova/api/__init__.py @@ -59,23 +59,13 @@ class API(wsgi.Router): mapper.connect("/", controller=self.osapi_versions, conditions=osapi_subdomain) - mapper.connect("/v1.0/{path_info:.*}", controller=openstack.API()) + mapper.connect("/v1.0/{path_info:.*}", controller=openstack.API(), + conditions=osapi_subdomain) mapper.connect("/", controller=self.ec2api_versions, conditions=ec2api_subdomain) mapper.connect("/services/{path_info:.*}", controller=ec2.API(), conditions=ec2api_subdomain) - -# mapper.connect("/", controller=self.osapi_versions, -# conditions=osapi_subdomain) -# mapper.connect("/v1.0/{path_info:.*}", controller=openstack.API(), -# conditions=osapi_subdomain) -# -# mapper.connect("/", controller=self.ec2api_versions, -# conditions=ec2api_subdomain) -# mapper.connect("/services/{path_info:.*}", controller=ec2.API(), -# conditions=ec2api_subdomain) - mrh = metadatarequesthandler.MetadataRequestHandler() for s in ['/latest', '/2009-04-04', diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index 280e2349e..6a35567ff 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -156,8 +156,6 @@ class Controller(wsgi.Controller): except exception.TimeoutException, e: return exc.HTTPRequestTimeout() try: - # The ID passed in is actually the internal_id of the - # instance, not the value of the id column in the DB. instance = self.compute_api.get(ctxt, id) self.compute_api.update(ctxt, instance.id, **update_dict) except exception.NotFound: -- cgit From 5d9ad54cc38283d0b946779f4235f54370b12489 Mon Sep 17 00:00:00 2001 From: Ed Leafe Date: Fri, 7 Jan 2011 15:50:43 -0500 Subject: incorporated changes suggested by eday --- nova/api/openstack/servers.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'nova/api') diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index c71cb8562..c97be86a2 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -144,17 +144,14 @@ class Controller(wsgi.Controller): ctxt = req.environ['nova.context'] update_dict = {} - func = None if 'adminPass' in inst_dict['server']: update_dict['admin_pass'] = inst_dict['server']['adminPass'] - func = self.compute_api.set_admin_password - if 'name' in inst_dict['server']: - update_dict['display_name'] = inst_dict['server']['name'] - if func: try: - func(ctxt, id) + self.compute_api.set_admin_password(ctxt, id) except exception.TimeoutException, e: return exc.HTTPRequestTimeout() + if 'name' in inst_dict['server']: + update_dict['display_name'] = inst_dict['server']['name'] try: self.compute_api.update(ctxt, id, **update_dict) except exception.NotFound: -- cgit From b8fc639af336630c56ce3807639a5e26c0d07982 Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Fri, 7 Jan 2011 13:02:55 -0800 Subject: set the hostname factory in the service init --- nova/api/ec2/cloud.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'nova/api') diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index 8e3091a68..b16ab42bd 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -93,8 +93,10 @@ class CloudController(object): def __init__(self): self.network_manager = utils.import_object(FLAGS.network_manager) self.image_service = utils.import_object(FLAGS.image_service) - self.compute_api = compute_api.ComputeAPI(self.network_manager, - self.image_service) + self.compute_api = compute_api.ComputeAPI( + network_manager=self.network_manager, + image_service=self.image_service, + hostname_factory=internal_id_to_ec2_id) self.setup() def __str__(self): @@ -807,7 +809,6 @@ class CloudController(object): key_name=kwargs.get('key_name'), user_data=kwargs.get('user_data'), security_group=kwargs.get('security_group'), - hostname_format='ec2', availability_zone=kwargs.get('placement', {}).get( 'AvailabilityZone')) return self._format_run_instances(context, -- cgit From a0ec77b597713fd9a4be5bb7b892eba4ac53e625 Mon Sep 17 00:00:00 2001 From: Ed Leafe Date: Fri, 7 Jan 2011 15:56:32 -0600 Subject: Reverted formatting change no longer necessary --- nova/api/openstack/servers.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'nova/api') diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index d8a7ca161..764c843ac 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -104,8 +104,7 @@ class Controller(wsgi.Controller): def show(self, req, id): """ Returns server details by server id """ try: - instance = self.compute_api.get( - req.environ['nova.context'], id) + instance = self.compute_api.get(req.environ['nova.context'], id) return _translate_detail_keys(instance) except exception.NotFound: return faults.Fault(exc.HTTPNotFound()) -- cgit From d79600c1029ab91de8a81809df9efddc762351c0 Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Fri, 7 Jan 2011 16:42:38 -0800 Subject: small cleanups --- 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 0953b01ed..3f0fdc575 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -49,7 +49,7 @@ def _translate_detail_keys(inst): power_state.SHUTOFF: 'active', power_state.CRASHED: 'error'} inst_dict = {} - print inst + mapped_keys = dict(status='state', imageId='image_id', flavorId='instance_type', name='display_name', id='id') -- cgit From d368d182d7fa4b0f0cd9c7c5ad1e804b19365b26 Mon Sep 17 00:00:00 2001 From: Nachi Ueno Date: Wed, 12 Jan 2011 12:05:27 +0900 Subject: Add DescribeInstanceV6 for backward compatibility --- nova/api/ec2/cloud.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'nova/api') diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index 8c925ffee..3d071782c 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -643,15 +643,21 @@ class CloudController(object): def describe_instances(self, context, **kwargs): return self._format_describe_instances(context) + def describe_instances_v6(self, context, **kwargs): + return self._format_describe_instances(context) + def _format_describe_instances(self, context): return {'reservationSet': self._format_instances(context)} + def _format_describe_instances_v6(self, context): + return {'reservationSet': self._format_instances(context,None,True)} + def _format_run_instances(self, context, reservation_id): i = self._format_instances(context, reservation_id) assert len(i) == 1 return i[0] - def _format_instances(self, context, reservation_id=None): + def _format_instances(self, context, reservation_id=None,use_v6=False): reservations = {} if reservation_id: instances = db.instance_get_all_by_reservation(context, @@ -677,7 +683,7 @@ class CloudController(object): if instance['fixed_ip']['floating_ips']: fixed = instance['fixed_ip'] floating_addr = fixed['floating_ips'][0]['address'] - if instance['fixed_ip']['network'] and FLAGS.use_ipv6: + if instance['fixed_ip']['network'] and use_v6: i['dnsNameV6'] = utils.to_global_ipv6( instance['fixed_ip']['network']['cidr_v6'], instance['mac_address']) -- cgit From 7a6b7c32ed25d1edc58b924ce5621dc0d8de9686 Mon Sep 17 00:00:00 2001 From: Nachi Ueno Date: Wed, 12 Jan 2011 03:50:09 -0500 Subject: Fixed bug --- 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 3d071782c..d6f164b5c 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -644,7 +644,7 @@ class CloudController(object): return self._format_describe_instances(context) def describe_instances_v6(self, context, **kwargs): - return self._format_describe_instances(context) + return self._format_describe_instances_v6(context) def _format_describe_instances(self, context): return {'reservationSet': self._format_instances(context)} -- cgit From a6a2a057d8a027781e4270c9abc4f815c67293ec Mon Sep 17 00:00:00 2001 From: Nachi Ueno Date: Wed, 12 Jan 2011 10:12:18 -0500 Subject: Fixed syntax errors --- 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 72d7bcc95..c5c99f132 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -610,7 +610,7 @@ class CloudController(object): def describe_instances_v6(self, context, **kwargs): kwargs['use_v6'] = True - return self._format_describe_instances_v6(context, **kwargs) + return self._format_describe_instances(context, **kwargs) def _format_describe_instances(self, context, **kwargs): return {'reservationSet': self._format_instances(context, **kwargs)} -- cgit From 76e875476848ee7f4aa483f65484903115e2bb49 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Fri, 14 Jan 2011 10:25:44 -0800 Subject: import re, remove extra call in cloud.py. Move get_console_output to compute_api --- nova/api/ec2/cloud.py | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) (limited to 'nova/api') diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index 630aaeaf2..4adcb7415 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -130,15 +130,6 @@ class CloudController(object): result[key] = [line] return result - def _trigger_refresh_security_group(self, context, security_group): - nodes = set([instance['host'] for instance in security_group.instances - if instance['host'] is not None]) - for node in nodes: - rpc.cast(context, - '%s.%s' % (FLAGS.compute_topic, node), - {"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: @@ -522,13 +513,7 @@ class CloudController(object): # instance_id is passed in as a list of instances ec2_id = instance_id[0] instance_id = ec2_id_to_id(ec2_id) - instance_ref = self.compute_api.get(context, instance_id) - output = rpc.call(context, - '%s.%s' % (FLAGS.compute_topic, - instance_ref['host']), - {"method": "get_console_output", - "args": {"instance_id": instance_ref['id']}}) - + output = self.compute_api.get_console_output(context, instance_id) now = datetime.datetime.utcnow() return {"InstanceId": ec2_id, "Timestamp": now, -- cgit From d0713a6a2149274eeeef6fd22e7da4706a8190ec Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Fri, 14 Jan 2011 11:36:48 -0800 Subject: removed rpc in cloud --- nova/api/ec2/cloud.py | 1 - 1 file changed, 1 deletion(-) (limited to 'nova/api') diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index 4adcb7415..fb7e6a59f 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -37,7 +37,6 @@ from nova import exception from nova import flags from nova import log as logging from nova import network -from nova import rpc from nova import utils from nova import volume from nova.compute import instance_types -- cgit From 69c11c27c20c74aced491ecfe78a80872ad6232a Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Fri, 14 Jan 2011 17:54:36 -0800 Subject: pep8 fixes... largely to things from trunk? --- nova/api/ec2/cloud.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'nova/api') diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index d1aec23be..a1ae70fb0 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -515,7 +515,8 @@ class CloudController(object): # instance_id is passed in as a list of instances ec2_id = instance_id[0] instance_id = ec2_id_to_id(ec2_id) - output = self.compute_api.get_console_output(context, instance_id=instance_id) + output = self.compute_api.get_console_output( + context, instance_id=instance_id) now = datetime.datetime.utcnow() return {"InstanceId": ec2_id, "Timestamp": now, -- cgit