summaryrefslogtreecommitdiff
path: root/bin
diff options
context:
space:
mode:
authorMichael Basnight <mbasnight@gmail.com>2012-02-19 10:41:59 -0600
committerjenkins-reddwarf <mbasnigh@rackspace.com>2012-02-19 11:06:49 -0600
commitdc5a1bb8c3ebd274b2502160eaea450b58fe3b80 (patch)
treec1f88df5914e76a67ede976120efbf96a834e69c /bin
parentf66d94b3a1620f6e2afac51c68ec3f0c82ad8811 (diff)
downloadtrove-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-xbin/reddwarf-api-os-database70
-rwxr-xr-xbin/reddwarf-cli304
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()
+