summaryrefslogtreecommitdiffstats
path: root/nova
diff options
context:
space:
mode:
authorAndy Smith <code@term.ie>2010-12-27 15:15:24 -0800
committerAndy Smith <code@term.ie>2010-12-27 15:15:24 -0800
commit8e1b74aa1c5a2f9113473eedc8e35b38b41445ea (patch)
tree44311f33afa023cfd354889cb2d7b8e4dcbd028d /nova
parenta1b5220879632d093f450413f96668a8f77c0613 (diff)
downloadnova-8e1b74aa1c5a2f9113473eedc8e35b38b41445ea.tar.gz
nova-8e1b74aa1c5a2f9113473eedc8e35b38b41445ea.tar.xz
nova-8e1b74aa1c5a2f9113473eedc8e35b38b41445ea.zip
Added stack command-line tool
Diffstat (limited to 'nova')
-rw-r--r--nova/api/easy.py57
-rw-r--r--nova/compute/api.py6
-rw-r--r--nova/tests/easy_unittest.py6
-rw-r--r--nova/utils.py2
-rw-r--r--nova/wsgi.py3
5 files changed, 53 insertions, 21 deletions
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,
diff --git a/nova/compute/api.py b/nova/compute/api.py
index 5f18539a3..005ed7a68 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -40,6 +40,7 @@ def id_to_default_hostname(internal_id):
"""Default function to generate a hostname given an instance reference."""
return str(internal_id)
+
def id_to_ec2_hostname(internal_id):
digits = []
while internal_id != 0:
@@ -47,9 +48,11 @@ def id_to_ec2_hostname(internal_id):
digits.append('0123456789abcdefghijklmnopqrstuvwxyz'[remainder])
return "i-%s" % ''.join(reversed(digits))
+
HOSTNAME_FORMATTERS = {'default': id_to_default_hostname,
'ec2': id_to_ec2_hostname}
+
class ComputeAPI(base.Base):
"""API for interacting with the compute manager."""
@@ -63,6 +66,7 @@ class ComputeAPI(base.Base):
super(ComputeAPI, self).__init__(**kwargs)
def get_network_topic(self, context, instance_id):
+ """Get the network topic for an instance."""
try:
instance = self.db.instance_get_by_internal_id(context,
instance_id)
@@ -221,6 +225,7 @@ class ComputeAPI(base.Base):
return self.db.instance_update(context, instance_id, kwargs)
def delete_instance(self, context, instance_id):
+ """Terminate and remove an instance."""
logging.debug("Going to try and terminate %d" % instance_id)
try:
instance = self.db.instance_get_by_internal_id(context,
@@ -264,6 +269,7 @@ class ComputeAPI(base.Base):
return self.db.instance_get_all(context)
def get_instance(self, context, instance_id):
+ """Get information about a specific instance."""
rv = self.db.instance_get_by_internal_id(context, instance_id)
return dict(rv.iteritems())
diff --git a/nova/tests/easy_unittest.py b/nova/tests/easy_unittest.py
index 81990d842..cd13c7710 100644
--- a/nova/tests/easy_unittest.py
+++ b/nova/tests/easy_unittest.py
@@ -31,6 +31,7 @@ from nova.api import easy
from nova.compute import api as compute_api
from nova.tests import cloud_unittest
+
class FakeService(object):
def echo(self, context, data):
return {'data': data}
@@ -49,7 +50,7 @@ class EasyTestCase(test.TestCase):
easy.SundayMorning()))
self.auth_router = easy.DelegatedAuthMiddleware(self.router)
self.context = context.RequestContext('user1', 'proj1')
-
+
def tearDown(self):
easy.EASY_ROUTES = {}
@@ -61,7 +62,7 @@ class EasyTestCase(test.TestCase):
data = json.loads(resp.body)
self.assertEqual(data['user'], 'user1')
self.assertEqual(data['project'], 'proj1')
-
+
def test_json_params(self):
req = webob.Request.blank('/fake/echo')
req.environ['openstack.context'] = self.context
@@ -99,4 +100,3 @@ class EasyCloudTestCase(cloud_unittest.CloudTestCase):
def tearDown(self):
super(EasyCloudTestCase, self).tearDown()
easy.EASY_ROUTES = {}
-
diff --git a/nova/utils.py b/nova/utils.py
index 7a98ffa5a..337924f10 100644
--- a/nova/utils.py
+++ b/nova/utils.py
@@ -386,7 +386,7 @@ def dumps(value):
return json.dumps(value)
except TypeError:
pass
-
+
return json.dumps(to_primitive(value))
diff --git a/nova/wsgi.py b/nova/wsgi.py
index c40f043f9..564805ae7 100644
--- a/nova/wsgi.py
+++ b/nova/wsgi.py
@@ -105,8 +105,7 @@ class Application(object):
class Middleware(Application):
"""Base WSGI middleware.
-
- Modelled after Django's middleware this class allows you to
+
These classes require an application to be
initialized that will be called next. By default the middleware will
simply call its wrapped app, or you can override __call__ to customize its