diff options
author | Michael Basnight <mbasnight@gmail.com> | 2012-02-19 10:41:59 -0600 |
---|---|---|
committer | jenkins-reddwarf <mbasnigh@rackspace.com> | 2012-02-19 11:06:49 -0600 |
commit | dc5a1bb8c3ebd274b2502160eaea450b58fe3b80 (patch) | |
tree | c1f88df5914e76a67ede976120efbf96a834e69c /bin | |
parent | f66d94b3a1620f6e2afac51c68ec3f0c82ad8811 (diff) | |
download | trove-dc5a1bb8c3ebd274b2502160eaea450b58fe3b80.tar.gz |
Got a nice API shell working
* uses devstacks install for nova/keystone/et al
* talks to nova via novaclient.
* adds a few extensions to show how its done
* has a single call to list instances
* found a few minor bugs to discuss w/ nova crew
** Note in order to run this you have to mod the code downloaded by devstack
or have local symlinks to nova & novaclient in your src tree running trunk
This will get dealt with soon (it is a weekend!)
Diffstat (limited to 'bin')
-rwxr-xr-x | bin/reddwarf-api-os-database | 70 | ||||
-rwxr-xr-x | bin/reddwarf-cli | 304 |
2 files changed, 374 insertions, 0 deletions
diff --git a/bin/reddwarf-api-os-database b/bin/reddwarf-api-os-database new file mode 100755 index 00000000..611bb81a --- /dev/null +++ b/bin/reddwarf-api-os-database @@ -0,0 +1,70 @@ +#!/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. + +"""Starter script for Nova OS API.""" + +import eventlet +eventlet.monkey_patch() + +import os +import sys + + +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 flags +from nova import log as logging +from nova import service +from nova import utils +from nova import wsgi +from nova.openstack.common import cfg + +SERVICE_NAME="reddwarfapi_database" + +reddwarf_opts = [ + cfg.StrOpt('reddwarf_api_paste_config', + default='reddwarf-api-paste.ini', + help='Reddwarf API paste config'), + # port magic in service.WSGIService the name of the app has to be the same + # as the name of the service + cfg.IntOpt('%s_listen_port' % SERVICE_NAME, + default=8779, + help='Reddwarf API default port'), + cfg.MultiStrOpt('reddwarf_api_extension', + default=[ + 'reddwarf.api.database.contrib.standard_extensions' + ], + help='osapi compute extension to load'), + ] +FLAGS = flags.FLAGS +FLAGS.register_opts(reddwarf_opts) + + +if __name__ == '__main__': + utils.default_flagfile() + flags.FLAGS(sys.argv) + logging.setup() + utils.monkey_patch() + loader = wsgi.Loader(config_path=FLAGS.reddwarf_api_paste_config) + server = service.WSGIService(SERVICE_NAME, loader=loader) + service.serve(server) + service.wait() diff --git a/bin/reddwarf-cli b/bin/reddwarf-cli new file mode 100755 index 00000000..49f4da84 --- /dev/null +++ b/bin/reddwarf-cli @@ -0,0 +1,304 @@ +#!/usr/bin/env python + +# Copyright 2011 OpenStack LLC +# +# 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. + +""" +Reddwarf Command line tool +""" + +import json +import optparse +import os +import sys + + +# If ../reddwarf/__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, 'reddwarfclient', + '__init__.py')): + sys.path.insert(0, possible_topdir) +if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')): + sys.path.insert(0, possible_topdir) + + +from reddwarfclient import common + + +oparser = None + + +def _pretty_print(info): + print json.dumps(info, sort_keys=True, indent=4) + + +class InstanceCommands(object): + """Commands to perform various instances operations and actions""" + + def __init__(self): + pass + + def create(self, name, volume_size, + flavorRef="http://localhost:8775/v1.0/flavors/1"): + """Create a new instance""" + dbaas = common.get_client() + volume = {"size": volume_size} + try: + result = dbaas.instances.create(name, flavorRef, volume) + _pretty_print(result._info) + except: + print sys.exc_info()[1] + + def delete(self, id): + """Delete the specified instance""" + dbaas = common.get_client() + try: + result = dbaas.instances.delete(id) + if result: + print result + except: + print sys.exc_info()[1] + + def get(self, id): + """Get details for the specified instance""" + dbaas = common.get_client() + try: + _pretty_print(dbaas.instances.get(id)._info) + except: + print sys.exc_info()[1] + + def list(self): + """List all instances for account""" + dbaas = common.get_client() + try: + for instance in dbaas.instances.list(): + _pretty_print(instance._info) + except: + print sys.exc_info()[1] + + def resize(self, id, size): + """Resize an instance volume""" + dbaas = common.get_client() + try: + result = dbaas.instances.resize(id, size) + if result: + print result + except: + print sys.exc_info()[1] + + def restart(self, id): + """Restart the database""" + dbaas = common.get_client() + try: + result = dbaas.instances.restart(id) + if result: + print result + except: + print sys.exc_info()[1] + + +class FlavorsCommands(object): + """Commands for listing Flavors""" + + def __init__(self): + pass + + def list(self): + """List the available flavors""" + dbaas = common.get_client() + try: + for flavor in dbaas.flavors.list(): + _pretty_print(flavor._info) + except: + print sys.exc_info()[1] + + +class DatabaseCommands(object): + """Database CRUD operations on an instance""" + + def __init__(self): + pass + + def create(self, id, dbname): + """Create a database""" + dbaas = common.get_client() + try: + databases = [{'name': dbname}] + dbaas.databases.create(id, databases) + except: + print sys.exc_info()[1] + + def delete(self, id, dbname): + """Delete a database""" + dbaas = common.get_client() + try: + dbaas.databases.delete(id, dbname) + except: + print sys.exc_info()[1] + + def list(self, id): + """List the databases""" + dbaas = common.get_client() + try: + for database in dbaas.databases.list(id): + _pretty_print(database._info) + except: + print sys.exc_info()[1] + + +class UserCommands(object): + """User CRUD operations on an instance""" + + def __init__(self): + pass + + def create(self, id, username, password, dbname, *args): + """Create a user in instance, with access to one or more databases""" + dbaas = common.get_client() + try: + databases = [{'name': dbname}] + [databases.append({"name": db}) for db in args] + users = [{'name': username, 'password': password, + 'databases': databases}] + dbaas.users.create(id, users) + except: + print sys.exc_info()[1] + + def delete(self, id, user): + """Delete the specified user""" + dbaas = common.get_client() + try: + dbaas.users.delete(id, user) + except: + print sys.exc_info()[1] + + def list(self, id): + """List all the users for an instance""" + dbaas = common.get_client() + try: + for user in dbaas.users.list(id): + _pretty_print(user._info) + except: + print sys.exc_info()[1] + + +class RootCommands(object): + """Root user related operations on an instance""" + + def __init__(self): + pass + + def create(self, id): + """Enable the instance's root user.""" + dbaas = common.get_client() + try: + user, password = dbaas.root.create(id) + print "User:\t\t%s\nPassword:\t%s" % (user, password) + except: + print sys.exc_info()[1] + + def enabled(self, id): + """Check the instance for root access""" + dbaas = common.get_client() + try: + _pretty_print(dbaas.root.is_root_enabled(id)) + except: + print sys.exc_info()[1] + + +class VersionCommands(object): + """List available versions""" + + def __init__(self): + pass + + def list(self, url): + """List all the supported versions""" + dbaas = common.get_client() + try: + versions = dbaas.versions.index(url) + for version in versions: + _pretty_print(version._info) + except: + print sys.exc_info()[1] + + +def config_options(): + global oparser + oparser.add_option("-u", "--url", default="http://localhost:5000/v1.1", + help="Auth API endpoint URL with port and version. \ + Default: http://localhost:5000/v1.1") + + +COMMANDS = {'auth': common.Auth, + 'instance': InstanceCommands, + 'flavor': FlavorsCommands, + 'database': DatabaseCommands, + 'user': UserCommands, + 'root': RootCommands, + 'version': VersionCommands} + + +def main(): + # Parse arguments + global oparser + oparser = optparse.OptionParser("%prog [options] <cmd> <action> <args>", + version='1.0') + config_options() + (options, args) = oparser.parse_args() + + if not args: + common.print_commands(COMMANDS) + + # Pop the command and check if it's in the known commands + cmd = args.pop(0) + if cmd in COMMANDS: + fn = COMMANDS.get(cmd) + command_object = fn() + + # Get a list of supported actions for the command + actions = common.methods_of(command_object) + + if len(args) < 1: + common.print_actions(cmd, actions) + + # Check for a valid action and perform that action + action = args.pop(0) + if action in actions: + fn = actions.get(action) + + try: + fn(*args) + sys.exit(0) + except TypeError as err: + print "Possible wrong number of arguments supplied." + print "%s %s: %s" % (cmd, action, fn.__doc__) + print "\t\t", [fn.func_code.co_varnames[i] for i in + range(fn.func_code.co_argcount)] + print "ERROR: %s" % err + except Exception: + print "Command failed, please check the log for more info." + raise + else: + common.print_actions(cmd, actions) + else: + common.print_commands(COMMANDS) + + +if __name__ == '__main__': + main() + |