From 2c14f1818d95cfc9e5dcbc6592b74cac79fb8dfb Mon Sep 17 00:00:00 2001 From: Joe Gordon Date: Mon, 9 Apr 2012 14:16:14 -0400 Subject: [PATCH] Remove nova Direct API blueprint remove-nova-direct-api Change-Id: I3229f8d7f37d66fcd6b978966f3a428a69e08bb1 --- bin/nova-direct-api | 110 ----------- bin/stack | 162 ---------------- nova/api/direct.py | 378 -------------------------------------- nova/tests/test_direct.py | 216 ---------------------- setup.py | 4 +- tools/pip-requires | 1 - 6 files changed, 1 insertion(+), 870 deletions(-) delete mode 100755 bin/nova-direct-api delete mode 100755 bin/stack delete mode 100644 nova/api/direct.py delete mode 100644 nova/tests/test_direct.py diff --git a/bin/nova-direct-api b/bin/nova-direct-api deleted file mode 100755 index 121a0b45c120..000000000000 --- a/bin/nova-direct-api +++ /dev/null @@ -1,110 +0,0 @@ -#!/usr/bin/env python -# pylint: disable=C0103 -# 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. - -"""Starter script for Nova Direct API.""" - -import eventlet -eventlet.monkey_patch() - -import os -import sys - -# If ../nova/__init__.py exists, add ../ to Python search path, so that -# it will override what happens to be installed in /usr/(local/)lib/python... -possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), - os.pardir, - os.pardir)) -if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')): - sys.path.insert(0, possible_topdir) - - -from nova import compute -from nova import flags -from nova import log as logging -from nova import network -from nova.openstack.common import cfg -from nova import service -from nova import utils -from nova import volume -from nova import wsgi -from nova.api import direct - - -direct_api_opts = [ - cfg.IntOpt('direct_port', - default=8001, - help='Direct API port'), - cfg.StrOpt('direct_host', - default='0.0.0.0', - help='Direct API host'), - ] - -FLAGS = flags.FLAGS -FLAGS.register_cli_opts(direct_api_opts) - - -# An example of an API that only exposes read-only methods. -# In this case we're just limiting which methods are exposed. -class ReadOnlyCompute(direct.Limited): - """Read-only Compute API.""" - - _allowed = ['get', 'get_all', 'get_console_output'] - - -# An example of an API that provides a backwards compatibility layer. -# In this case we're overwriting the implementation to ensure -# compatibility with an older version. In reality we would want the -# "description=None" to be part of the actual API so that code -# like this isn't even necessary, but this example shows what one can -# do if that isn't the situation. -class VolumeVersionOne(direct.Limited): - _allowed = ['create', 'delete', 'update', 'get'] - - def create(self, context, size, name): - self.proxy.create(context, size, name, description=None) - - -if __name__ == '__main__': - utils.default_flagfile() - FLAGS(sys.argv) - logging.setup() - - direct.register_service('compute', compute.API()) - direct.register_service('volume', volume.API()) - direct.register_service('network', network.API()) - direct.register_service('reflect', direct.Reflection()) - - # Here is how we could expose the code in the examples above. - #direct.register_service('compute-readonly', - # ReadOnlyCompute(compute.API())) - #direct.register_service('volume-v1', VolumeVersionOne(volume.API())) - - router = direct.Router() - with_json = direct.JsonParamsMiddleware(router) - with_req = direct.PostParamsMiddleware(with_json) - with_auth = direct.DelegatedAuthMiddleware(with_req) - - server = wsgi.Server("Direct API", - with_auth, - host=FLAGS.direct_host, - port=FLAGS.direct_port) - - service.serve(server) - service.wait() diff --git a/bin/stack b/bin/stack deleted file mode 100755 index 0b226b7c1294..000000000000 --- a/bin/stack +++ /dev/null @@ -1,162 +0,0 @@ -#!/usr/bin/env python -# 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. - -"""CLI for the Direct API.""" - -import eventlet -eventlet.monkey_patch() - -import json -import os -import pprint -import sys -import textwrap -import urllib -import urllib2 - -# If ../nova/__init__.py exists, add ../ to Python search path, so that -# it will override what happens to be installed in /usr/(local/)lib/python... -possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), - os.pardir, - os.pardir)) -if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')): - sys.path.insert(0, possible_topdir) - -import gflags - - -FLAGS = gflags.FLAGS -gflags.DEFINE_string('host', '127.0.0.1', 'Direct API host') -gflags.DEFINE_integer('port', 8001, 'Direct API host') -gflags.DEFINE_string('user', 'user1', 'Direct API username') -gflags.DEFINE_string('project', 'proj1', 'Direct API project') - - -USAGE = """usage: stack [options] [arg1=value arg2=value] - - `stack help` should output the list of available controllers - `stack ` should output the available methods for that controller - `stack help ` should do the same - `stack help ` should output info for a method -""" - - -def format_help(d): - """Format help text, keys are labels and values are descriptions.""" - MAX_INDENT = 30 - indent = max([len(k) for k in d]) - if indent > MAX_INDENT: - indent = MAX_INDENT - 6 - - out = [] - for k, v in sorted(d.iteritems()): - if (len(k) + 6) > MAX_INDENT: - out.extend([' %s' % k]) - initial_indent = ' ' * (indent + 6) - else: - initial_indent = ' %s ' % k.ljust(indent) - subsequent_indent = ' ' * (indent + 6) - t = textwrap.TextWrapper(initial_indent=initial_indent, - subsequent_indent=subsequent_indent) - out.extend(t.wrap(v)) - return out - - -def help_all(): - rv = do_request('reflect', 'get_controllers') - out = format_help(rv) - return (USAGE + str(FLAGS.MainModuleHelp()) + - '\n\nAvailable controllers:\n' + - '\n'.join(out) + '\n') - - -def help_controller(controller): - rv = do_request('reflect', 'get_methods') - methods = dict([(k.split('/')[2], v) for k, v in rv.iteritems() - if k.startswith('/%s' % controller)]) - return ('Available methods for %s:\n' % controller + - '\n'.join(format_help(methods))) - - -def help_method(controller, method): - rv = do_request('reflect', - 'get_method_info', - {'method': '/%s/%s' % (controller, method)}) - - sig = '%s(%s):' % (method, ', '.join(['='.join(x) for x in rv['args']])) - out = textwrap.wrap(sig, subsequent_indent=' ' * len('%s(' % method)) - out.append('\n' + rv['doc']) - return '\n'.join(out) - - -def do_request(controller, method, params=None): - if params: - data = urllib.urlencode(params) - else: - data = None - - url = 'http://%s:%s/%s/%s' % (FLAGS.host, FLAGS.port, controller, method) - headers = {'X-OpenStack-User': FLAGS.user, - 'X-OpenStack-Project': FLAGS.project} - - req = urllib2.Request(url, data, headers) - try: - resp = urllib2.urlopen(req) - except urllib2.HTTPError, e: - print e.read() - sys.exit(1) - except urllib2.URLError, e: - print 'Failed to connect to %s: %s' % (url, e.reason) - sys.exit(1) - return json.loads(resp.read()) - - -if __name__ == '__main__': - args = FLAGS(sys.argv) - - cmd = args.pop(0) - if not args: - print help_all() - sys.exit() - - first = args.pop(0) - if first == 'help': - action = help_all - params = [] - if args: - params.append(args.pop(0)) - action = help_controller - if args: - params.append(args.pop(0)) - action = help_method - print action(*params) - sys.exit(0) - - controller = first - if not args: - print help_controller(controller) - sys.exit() - - method = args.pop(0) - params = {} - for x in args: - key, value = x.split('=', 1) - params[key] = value - - pprint.pprint(do_request(controller, method, params)) diff --git a/nova/api/direct.py b/nova/api/direct.py deleted file mode 100644 index b3d683b53da5..000000000000 --- a/nova/api/direct.py +++ /dev/null @@ -1,378 +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 - -import nova.api.openstack.wsgi -from nova import context -from nova import exception -from nova import utils -from nova import wsgi - - -# Global storage for registering modules. -ROUTES = {} - - -def register_service(path, handle): - """Register a service handle at a given path. - - Services registered in this way will be made available to any instances of - nova.api.direct.Router. - - :param path: `routes` path, can be a basic string like "/path" - :param handle: an object whose methods will be made available via the api - - """ - ROUTES[path] = handle - - -class Router(wsgi.Router): - """A simple WSGI router configured via `register_service`. - - This is a quick way to attach multiple services to a given endpoint. - It will automatically load the routes registered in the `ROUTES` global. - - TODO(termie): provide a paste-deploy version of this. - - """ - - 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): - """A simple and naive authentication middleware. - - Designed mostly to provide basic support for alternative authentication - schemes, this middleware only desires the identity of the user and will - generate the appropriate nova.context.RequestContext for the rest of the - application. This allows any middleware above it in the stack to - authenticate however it would like while only needing to conform to a - minimal interface. - - Expects two headers to determine identity: - - X-OpenStack-User - - X-OpenStack-Project - - This middleware is tied to identity management and will need to be kept - in sync with any changes to the way identity is dealt with internally. - - """ - - def process_request(self, request): - os_user = request.headers['X-OpenStack-User'] - os_project = request.headers['X-OpenStack-Project'] - context_ref = context.RequestContext(user_id=os_user, - project_id=os_project) - request.environ['openstack.context'] = context_ref - - -class JsonParamsMiddleware(wsgi.Middleware): - """Middleware to allow method arguments to be passed as serialized JSON. - - Accepting arguments as JSON is useful for accepting data that may be more - complex than simple primitives. - - In this case we accept it as urlencoded data under the key 'json' as in - json= but this could be extended to accept raw JSON - in the POST body. - - Filters out the parameters `self`, `context` and anything beginning with - an underscore. - - """ - - 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): - """Middleware to allow method arguments to be passed as POST parameters. - - Filters out the parameters `self`, `context` and anything beginning with - an underscore. - - """ - - 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. - - This is an object that expects to be registered via register_service. - These methods allow the endpoint to be self-describing. They introspect - the exposed methods and provide call signatures and documentation for - them allowing quick experimentation. - - """ - - def __init__(self): - self._methods = {} - self._controllers = {} - - def _gather_methods(self): - """Introspect available methods and generate documentation for them.""" - 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],)) - - if f.__doc__: - short_doc = f.__doc__.split('\n')[0] - doc = f.__doc__ - else: - short_doc = doc = _('not available') - - methods['/%s/%s' % (route, k)] = { - 'short_doc': short_doc, - 'doc': 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(object): - """Wrapper to dynamically provide a WSGI controller for arbitrary objects. - - With lightweight introspection allows public methods on the object to - be accessed via simple WSGI routing and parameters and serializes the - return values. - - Automatically used be nova.api.direct.Router to wrap registered instances. - - """ - - def __init__(self, service_handle): - self.service_handle = service_handle - - @webob.dec.wsgify(RequestClass=nova.api.openstack.wsgi.Request) - 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) - - # NOTE(vish): make sure we have no unicode keys for py2.6. - params = dict([(str(k), v) for (k, v) in params.iteritems()]) - result = method(context, **params) - - if result is None or isinstance(result, basestring): - return result - - try: - content_type = req.best_match_content_type() - serializer = { - 'application/xml': nova.api.openstack.wsgi.XMLDictSerializer(), - 'application/json': nova.api.openstack.wsgi.JSONDictSerializer(), - }[content_type] - return serializer.serialize(result) - except Exception, e: - raise exception.Error(_("Returned non-serializeable type: %s") - % result) - - -class Limited(object): - __notdoc = """Limit the available methods on a given object. - - (Not a docstring so that the docstring can be conditionally overridden.) - - Useful when defining a public API that only exposes a subset of an - internal API. - - Expected usage of this class is to define a subclass that lists the allowed - methods in the 'allowed' variable. - - Additionally where appropriate methods can be added or overwritten, for - example to provide backwards compatibility. - - The wrapping approach has been chosen so that the wrapped API can maintain - its own internal consistency, for example if it calls "self.create" it - should get its own create method rather than anything we do here. - - """ - - _allowed = None - - def __init__(self, proxy): - self._proxy = proxy - if not self.__doc__: # pylint: disable=E0203 - self.__doc__ = proxy.__doc__ - if not self._allowed: - self._allowed = [] - - def __getattr__(self, key): - """Only return methods that are named in self._allowed.""" - if key not in self._allowed: - raise AttributeError() - return getattr(self._proxy, key) - - def __dir__(self): - """Only return methods that are named in self._allowed.""" - return [x for x in dir(self._proxy) if x in self._allowed] - - -class Proxy(object): - """Pretend a Direct API endpoint is an object. - - This is mostly useful in testing at the moment though it should be easily - extendable to provide a basic API library functionality. - - In testing we use this to stub out internal objects to verify that results - from the API are serializable. - - """ - - def __init__(self, app, prefix=None): - self.app = app - self.prefix = prefix - - def __do_request(self, path, context, **kwargs): - req = wsgi.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/tests/test_direct.py b/nova/tests/test_direct.py deleted file mode 100644 index cf92dfcaaca8..000000000000 --- a/nova/tests/test_direct.py +++ /dev/null @@ -1,216 +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. - -"""Tests for Direct API.""" - -import json - -import webob - -from nova import context -from nova import exception -from nova import test -from nova.api import direct - - -class ArbitraryObject(object): - pass - - -class FakeService(object): - def echo(self, context, data): - return {'data': data} - - def context(self, context): - return {'user': context.user_id, - 'project': context.project_id} - - def echo_data_directly(self, context, data): - return data - - def invalid_return(self, context): - return ArbitraryObject() - - -class MyLimited(direct.Limited): - _allowed = ['var1', 'func1'] - - -class MyProxy(object): - var1 = var2 = True - - def func1(self): - return True - - def func2(self): - return True - - -class DirectTestCase(test.TestCase): - def setUp(self): - super(DirectTestCase, self).setUp() - direct.register_service('fake', FakeService()) - self.router = direct.PostParamsMiddleware( - direct.JsonParamsMiddleware( - direct.Router())) - self.auth_router = direct.DelegatedAuthMiddleware(self.router) - self.context = context.RequestContext('user1', 'proj1') - - def tearDown(self): - direct.ROUTES = {} - super(DirectTestCase, self).tearDown() - - def test_delegated_auth(self): - req = webob.Request.blank('/fake/context') - req.headers['X-OpenStack-User'] = 'user1' - req.headers['X-OpenStack-Project'] = 'proj1' - resp = req.get_response(self.auth_router) - self.assertEqual(resp.status_int, 200) - 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 - req.method = 'POST' - req.body = 'json=%s' % json.dumps({'data': 'foo'}) - resp = req.get_response(self.router) - self.assertEqual(resp.status_int, 200) - resp_parsed = json.loads(resp.body) - self.assertEqual(resp_parsed['data'], 'foo') - - def test_filter_json_params(self): - req = webob.Request.blank('/fake/echo') - req.environ['openstack.context'] = self.context - req.method = 'POST' - req.body = 'json=%s' % json.dumps({'data': 'foo', - '_underscored': 'ignoreMe', - 'self': 'ignoreMe', - 'context': 'ignoreMe'}) - resp = req.get_response(self.router) - self.assertEqual(resp.status_int, 200) - resp_parsed = json.loads(resp.body) - self.assertEqual(resp_parsed['data'], 'foo') - self.assertNotIn('_underscored', resp_parsed) - self.assertNotIn('self', resp_parsed) - self.assertNotIn('context', resp_parsed) - - def test_post_params(self): - req = webob.Request.blank('/fake/echo') - req.environ['openstack.context'] = self.context - req.method = 'POST' - req.body = 'data=foo' - resp = req.get_response(self.router) - self.assertEqual(resp.status_int, 200) - resp_parsed = json.loads(resp.body) - self.assertEqual(resp_parsed['data'], 'foo') - - def test_filter_post_params(self): - req = webob.Request.blank('/fake/echo') - req.environ['openstack.context'] = self.context - req.method = 'POST' - req.body = ('data=foo&_underscored=ignoreMe&self=ignoreMe&context=' - 'ignoreMe') - resp = req.get_response(self.router) - self.assertEqual(resp.status_int, 200) - resp_parsed = json.loads(resp.body) - self.assertEqual(resp_parsed['data'], 'foo') - self.assertNotIn('_underscored', resp_parsed) - self.assertNotIn('self', resp_parsed) - self.assertNotIn('context', resp_parsed) - - def test_string_resp(self): - req = webob.Request.blank('/fake/echo_data_directly') - req.environ['openstack.context'] = self.context - req.method = 'POST' - req.body = 'data=foo' - resp = req.get_response(self.router) - self.assertEqual(resp.status_int, 200) - self.assertEqual(resp.body, 'foo') - - def test_invalid(self): - req = webob.Request.blank('/fake/invalid_return') - req.environ['openstack.context'] = self.context - req.method = 'POST' - self.assertRaises(exception.Error, req.get_response, self.router) - - def test_proxy(self): - proxy = direct.Proxy(self.router) - rv = proxy.fake.echo(self.context, data='baz') - self.assertEqual(rv['data'], 'baz') - - -class LimitedTestCase(test.TestCase): - def test_limited_class_getattr(self): - limited = MyLimited(MyProxy()) - - # Allowed are still visible - self.assertTrue(limited.func1()) - self.assertTrue(limited.var1) - - # Non-allowed are no longer visible - self.assertRaises(AttributeError, getattr, limited, 'func2') - self.assertRaises(AttributeError, getattr, limited, 'var2') - - def test_limited_class_dir(self): - limited = MyLimited(MyProxy()) - - # Allowed are still visible - self.assertIn('func1', dir(limited)) - self.assertIn('var1', dir(limited)) - - # Non-allowed are no longer visible - self.assertNotIn('func2', dir(limited)) - self.assertNotIn('var2', dir(limited)) - - def test_limited_class_no_allowed(self): - - # New MyLimited class with no _allowed variable - class MyLimited(direct.Limited): - pass - - limited = MyLimited(MyProxy()) - - # Nothing in MyProxy object visible now - self.assertNotIn('func1', dir(limited)) - self.assertNotIn('var1', dir(limited)) - - -# NOTE(jkoelker): This fails using the EC2 api -#class DirectCloudTestCase(test_cloud.CloudTestCase): -# def setUp(self): -# super(DirectCloudTestCase, self).setUp() -# compute_handle = compute.API(image_service=self.cloud.image_service) -# volume_handle = volume.API() -# network_handle = network.API() -# direct.register_service('compute', compute_handle) -# direct.register_service('volume', volume_handle) -# direct.register_service('network', network_handle) -# -# self.router = direct.JsonParamsMiddleware(direct.Router()) -# proxy = direct.Proxy(self.router) -# self.cloud.compute_api = proxy.compute -# self.cloud.volume_api = proxy.volume -# self.cloud.network_api = proxy.network -# compute_handle.volume_api = proxy.volume -# compute_handle.network_api = proxy.network -# -# def tearDown(self): -# super(DirectCloudTestCase, self).tearDown() -# direct.ROUTES = {} diff --git a/setup.py b/setup.py index f3b0baba577d..32b59511f3be 100644 --- a/setup.py +++ b/setup.py @@ -76,13 +76,11 @@ setuptools.setup(name='nova', 'bin/nova-console', 'bin/nova-consoleauth', 'bin/nova-dhcpbridge', - 'bin/nova-direct-api', 'bin/nova-manage', 'bin/nova-network', 'bin/nova-objectstore', 'bin/nova-rootwrap', 'bin/nova-scheduler', 'bin/nova-volume', - 'bin/nova-xvpvncproxy', - 'bin/stack'], + 'bin/nova-xvpvncproxy'], py_modules=[]) diff --git a/tools/pip-requires b/tools/pip-requires index 77ceb9b5a350..aa5cbe782029 100644 --- a/tools/pip-requires +++ b/tools/pip-requires @@ -8,7 +8,6 @@ kombu==1.0.4 lockfile==0.8 lxml==2.3 python-daemon==1.5.5 -python-gflags==1.3 python-novaclient routes==1.12.3 WebOb==1.0.8