Added stack command-line tool
This commit is contained in:
61
bin/nova-easy-api
Executable file
61
bin/nova-easy-api
Executable file
@@ -0,0 +1,61 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# pylint: disable-msg=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 Easy API."""
|
||||||
|
|
||||||
|
import gettext
|
||||||
|
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)
|
||||||
|
|
||||||
|
gettext.install('nova', unicode=1)
|
||||||
|
|
||||||
|
from nova import flags
|
||||||
|
from nova import utils
|
||||||
|
from nova import wsgi
|
||||||
|
from nova.api import easy
|
||||||
|
from nova.compute import api as compute_api
|
||||||
|
|
||||||
|
|
||||||
|
FLAGS = flags.FLAGS
|
||||||
|
flags.DEFINE_integer('easy_port', 8001, 'Easy API port')
|
||||||
|
flags.DEFINE_string('easy_host', '0.0.0.0', 'Easy API host')
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
utils.default_flagfile()
|
||||||
|
FLAGS(sys.argv)
|
||||||
|
|
||||||
|
easy.register_service('compute', compute_api.ComputeAPI())
|
||||||
|
easy.register_service('reflect', easy.Reflection())
|
||||||
|
router = easy.SundayMorning()
|
||||||
|
with_json = easy.JsonParamsMiddleware(router)
|
||||||
|
with_req = easy.ReqParamsMiddleware(with_json)
|
||||||
|
with_auth = easy.DelegatedAuthMiddleware(with_req)
|
||||||
|
|
||||||
|
server = wsgi.Server()
|
||||||
|
server.start(with_auth, FLAGS.easy_port, host=FLAGS.easy_host)
|
||||||
|
server.wait()
|
||||||
145
bin/stack
Executable file
145
bin/stack
Executable file
@@ -0,0 +1,145 @@
|
|||||||
|
#!/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 Easy API."""
|
||||||
|
|
||||||
|
import eventlet
|
||||||
|
eventlet.monkey_patch()
|
||||||
|
|
||||||
|
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
|
||||||
|
from nova import utils
|
||||||
|
|
||||||
|
|
||||||
|
FLAGS = gflags.FLAGS
|
||||||
|
gflags.DEFINE_string('host', '127.0.0.1', 'Easy API host')
|
||||||
|
gflags.DEFINE_integer('port', 8001, 'Easy API host')
|
||||||
|
gflags.DEFINE_string('user', 'user1', 'Easy API username')
|
||||||
|
gflags.DEFINE_string('project', 'proj1', 'Easy 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."""
|
||||||
|
indent = max([len(k) for k in d])
|
||||||
|
out = []
|
||||||
|
for k, v in d.iteritems():
|
||||||
|
t = textwrap.TextWrapper(initial_indent=' %s ' % k.ljust(indent),
|
||||||
|
subsequent_indent=' ' * (indent + 6))
|
||||||
|
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)
|
||||||
|
resp = urllib2.urlopen(req)
|
||||||
|
return utils.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 = args.split('=', 1)
|
||||||
|
params[key] = value
|
||||||
|
|
||||||
|
pprint.pprint(do_request(controller, method, params))
|
||||||
@@ -31,6 +31,7 @@ from nova.api import easy
|
|||||||
from nova.compute import api as compute_api
|
from nova.compute import api as compute_api
|
||||||
from nova.tests import cloud_unittest
|
from nova.tests import cloud_unittest
|
||||||
|
|
||||||
|
|
||||||
class FakeService(object):
|
class FakeService(object):
|
||||||
def echo(self, context, data):
|
def echo(self, context, data):
|
||||||
return {'data': data}
|
return {'data': data}
|
||||||
@@ -49,7 +50,7 @@ class EasyTestCase(test.TestCase):
|
|||||||
easy.SundayMorning()))
|
easy.SundayMorning()))
|
||||||
self.auth_router = easy.DelegatedAuthMiddleware(self.router)
|
self.auth_router = easy.DelegatedAuthMiddleware(self.router)
|
||||||
self.context = context.RequestContext('user1', 'proj1')
|
self.context = context.RequestContext('user1', 'proj1')
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
easy.EASY_ROUTES = {}
|
easy.EASY_ROUTES = {}
|
||||||
|
|
||||||
@@ -61,7 +62,7 @@ class EasyTestCase(test.TestCase):
|
|||||||
data = json.loads(resp.body)
|
data = json.loads(resp.body)
|
||||||
self.assertEqual(data['user'], 'user1')
|
self.assertEqual(data['user'], 'user1')
|
||||||
self.assertEqual(data['project'], 'proj1')
|
self.assertEqual(data['project'], 'proj1')
|
||||||
|
|
||||||
def test_json_params(self):
|
def test_json_params(self):
|
||||||
req = webob.Request.blank('/fake/echo')
|
req = webob.Request.blank('/fake/echo')
|
||||||
req.environ['openstack.context'] = self.context
|
req.environ['openstack.context'] = self.context
|
||||||
@@ -99,4 +100,3 @@ class EasyCloudTestCase(cloud_unittest.CloudTestCase):
|
|||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
super(EasyCloudTestCase, self).tearDown()
|
super(EasyCloudTestCase, self).tearDown()
|
||||||
easy.EASY_ROUTES = {}
|
easy.EASY_ROUTES = {}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user