summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Gordon <jogo@cloudscaling.com>2012-04-09 14:16:14 -0400
committerJoe Gordon <jogo@cloudscaling.com>2012-04-10 09:23:30 -0400
commit2c14f1818d95cfc9e5dcbc6592b74cac79fb8dfb (patch)
tree6413fdb20400d9fee106663c546a840a459a0a27
parent384b758166ed72fc16da7c5ad18eedc044bbc633 (diff)
downloadnova-2c14f1818d95cfc9e5dcbc6592b74cac79fb8dfb.tar.gz
Remove nova Direct API
blueprint remove-nova-direct-api Change-Id: I3229f8d7f37d66fcd6b978966f3a428a69e08bb1
-rwxr-xr-xbin/nova-direct-api110
-rwxr-xr-xbin/stack162
-rw-r--r--nova/api/direct.py378
-rw-r--r--nova/tests/test_direct.py216
-rw-r--r--setup.py4
-rw-r--r--tools/pip-requires1
6 files changed, 1 insertions, 870 deletions
diff --git a/bin/nova-direct-api b/bin/nova-direct-api
deleted file mode 100755
index 121a0b45c1..0000000000
--- 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 0b226b7c12..0000000000
--- 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] <controller> <method> [arg1=value arg2=value]
-
- `stack help` should output the list of available controllers
- `stack <controller>` should output the available methods for that controller
- `stack help <controller>` should do the same
- `stack help <controller> <method>` 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 b3d683b53d..0000000000
--- 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=<urlencoded_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 cf92dfcaac..0000000000
--- 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 f3b0baba57..32b59511f3 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 77ceb9b5a3..aa5cbe7820 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