diff options
| author | Jesse Andrews <anotherjesse@gmail.com> | 2010-05-27 23:05:26 -0700 |
|---|---|---|
| committer | Jesse Andrews <anotherjesse@gmail.com> | 2010-05-27 23:05:26 -0700 |
| commit | bf6e6e718cdc7488e2da87b21e258ccc065fe499 (patch) | |
| tree | 51cf4f72047eb6b16079c7fe21e9822895541801 /bin | |
| download | nova-bf6e6e718cdc7488e2da87b21e258ccc065fe499.tar.gz nova-bf6e6e718cdc7488e2da87b21e258ccc065fe499.tar.xz nova-bf6e6e718cdc7488e2da87b21e258ccc065fe499.zip | |
initial commit
Diffstat (limited to 'bin')
| -rwxr-xr-x | bin/nova-api | 63 | ||||
| -rwxr-xr-x | bin/nova-compute | 97 | ||||
| -rwxr-xr-x | bin/nova-manage | 158 | ||||
| -rwxr-xr-x | bin/nova-objectstore | 49 | ||||
| -rwxr-xr-x | bin/nova-volume | 68 |
5 files changed, 435 insertions, 0 deletions
diff --git a/bin/nova-api b/bin/nova-api new file mode 100755 index 000000000..8fea1da4d --- /dev/null +++ b/bin/nova-api @@ -0,0 +1,63 @@ +#!/usr/bin/env python +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright [2010] [Anso Labs, 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. +""" + Tornado daemon for the main API endpoint. +""" + +import logging + +from nova import vendor +from tornado import httpserver +from tornado import ioloop + +from nova import flags +from nova import rpc +from nova import server +from nova import utils +from nova.auth import users +from nova.endpoint import admin +from nova.endpoint import api +from nova.endpoint import cloud + +FLAGS = flags.FLAGS + + +def main(_argv): + user_manager = users.UserManager() + controllers = { + 'Cloud': cloud.CloudController(), + 'Admin': admin.AdminController(user_manager) + } + _app = api.APIServerApplication(user_manager, controllers) + + conn = rpc.Connection.instance() + consumer = rpc.AdapterConsumer(connection=conn, + topic=FLAGS.cloud_topic, + proxy=controllers['Cloud']) + + io_inst = ioloop.IOLoop.instance() + _injected = consumer.attach_to_tornado(io_inst) + + http_server = httpserver.HTTPServer(_app) + http_server.listen(FLAGS.cc_port) + logging.debug('Started HTTP server on %s', FLAGS.cc_port) + io_inst.start() + + +if __name__ == '__main__': + utils.default_flagfile() + server.serve('nova-api', main) diff --git a/bin/nova-compute b/bin/nova-compute new file mode 100755 index 000000000..bd3648d20 --- /dev/null +++ b/bin/nova-compute @@ -0,0 +1,97 @@ +#!/usr/bin/env python +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright [2010] [Anso Labs, 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. +""" + Twistd daemon for the nova compute nodes. + Receives messages via AMQP, manages pool of worker threads + for async tasks. +""" + +import logging +import os +import sys + +# NOTE(termie): kludge so that we can run this from the bin directory in the +# checkout without having to screw with paths +NOVA_PATH = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'nova') +if os.path.exists(NOVA_PATH): + sys.path.insert(0, os.path.dirname(NOVA_PATH)) + +from nova import vendor +from carrot import connection +from carrot import messaging +from twisted.internet import task +from twisted.application import service + +from nova import flags +from nova import rpc +from nova import twistd +from nova.compute import node + + +FLAGS = flags.FLAGS +# NOTE(termie): This file will necessarily be re-imported under different +# context when the twistd.serve() call is made below so any +# flags we define here will have to be conditionally defined, +# flags defined by imported modules are safe. +if 'node_report_state_interval' not in FLAGS: + flags.DEFINE_integer('node_report_state_interval', 10, + 'seconds between nodes reporting state to cloud', + lower_bound=1) +logging.getLogger().setLevel(logging.DEBUG) + +def main(): + logging.warn('Starting compute node') + n = node.NetworkNode() + d = n.adopt_instances() + d.addCallback(lambda x: logging.info('Adopted %d instances', x)) + + conn = rpc.Connection.instance() + consumer_all = rpc.AdapterConsumer( + connection=conn, + topic='%s' % FLAGS.compute_topic, + proxy=n) + + consumer_node = rpc.AdapterConsumer( + connection=conn, + topic='%s.%s' % (FLAGS.compute_topic, FLAGS.node_name), + proxy=n) + + # heartbeat = task.LoopingCall(n.report_state) + # heartbeat.start(interval=FLAGS.node_report_state_interval, now=False) + + injected = consumer_all.attach_to_twisted() + injected = consumer_node.attach_to_twisted() + + # This is the parent service that twistd will be looking for when it + # parses this file, return it so that we can get it into globals below + application = service.Application('nova-compute') + n.setServiceParent(application) + return application + + +# NOTE(termie): When this script is executed from the commandline what it will +# actually do is tell the twistd application runner that it +# should run this file as a twistd application (see below). +if __name__ == '__main__': + twistd.serve(__file__) + +# NOTE(termie): When this script is loaded by the twistd application runner +# this code path will be executed and twistd will expect a +# variable named 'application' to be available, it will then +# handle starting it and stopping it. +if __name__ == '__builtin__': + application = main() diff --git a/bin/nova-manage b/bin/nova-manage new file mode 100755 index 000000000..d2108626b --- /dev/null +++ b/bin/nova-manage @@ -0,0 +1,158 @@ +#!/usr/bin/env python +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright [2010] [Anso Labs, 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. +""" + CLI interface for nova management. + Connects to the running ADMIN api in the api daemon. +""" + +import sys + +from nova import flags +from nova import utils +from nova.auth import users +from nova.compute import model +from nova.endpoint import cloud +import time + +FLAGS = flags.FLAGS + + +class UserCommands(object): + def __init__(self): + self.manager = users.UserManager.instance() + + def __print_export(self, user): + print 'export EC2_ACCESS_KEY=%s' % user.access + print 'export EC2_SECRET_KEY=%s' % user.secret + + def admin(self, name, access=None, secret=None): + """creates a new admin and prints exports + arguments: name [access] [secret]""" + user = self.manager.create_user(name, access, secret, True) + self.__print_export(user) + + def create(self, name, access=None, secret=None): + """creates a new user and prints exports + arguments: name [access] [secret]""" + user = self.manager.create_user(name, access, secret, False) + self.__print_export(user) + + def delete(self, name): + """deletes an existing user + arguments: name""" + self.manager.delete_user(name) + + def exports(self, name): + """prints access and secrets for user in export format + arguments: name""" + user = self.manager.get_user(name) + if user: + self.__print_export(user) + else: + print "User %s doesn't exist" % name + + def list(self): + """lists all users + arguments: <none>""" + for user in self.manager.get_users(): + print user.name + + def zip(self, name, filename='nova.zip'): + """exports credentials for user to a zip file + arguments: name [filename='nova.zip]""" + user = self.manager.get_user(name) + if user: + with open(filename, 'w') as f: + f.write(user.get_credentials()) + else: + print "User %s doesn't exist" % name + + +def usage(script_name): + print script_name + " category action [<args>]" + + +categories = [ + ('user', UserCommands), +] + + +def lazy_match(name, key_value_tuples): + """finds all objects that have a key that case insensitively contains [name] + key_value_tuples is a list of tuples of the form (key, value) + returns a list of tuples of the form (key, value)""" + return [(k, v) for (k, v) in key_value_tuples if k.lower().find(name.lower()) == 0] + + +def methods_of(obj): + """get all callable methods of an object that don't start with underscore + returns a list of tuples of the form (method_name, method)""" + return [(i, getattr(obj, i)) for i in dir(obj) if callable(getattr(obj, i)) and not i.startswith('_')] + + +if __name__ == '__main__': + utils.default_flagfile() + argv = FLAGS(sys.argv) + script_name = argv.pop(0) + if len(argv) < 1: + usage(script_name) + print "Available categories:" + for k, v in categories: + print "\t%s" % k + sys.exit(2) + category = argv.pop(0) + matches = lazy_match(category, categories) + if len(matches) == 0: + print "%s does not match any categories:" % category + for k, v in categories: + print "\t%s" % k + sys.exit(2) + if len(matches) > 1: + print "%s matched multiple categories:" % category + for k, v in matches: + print "\t%s" % k + sys.exit(2) + # instantiate the command group object + category, fn = matches[0] + command_object = fn() + actions = methods_of(command_object) + if len(argv) < 1: + usage(script_name) + print "Available actions for %s category:" % category + for k, v in actions: + print "\t%s" % k + sys.exit(2) + action = argv.pop(0) + matches = lazy_match(action, actions) + if len(matches) == 0: + print "%s does not match any actions" % action + for k, v in actions: + print "\t%s" % k + sys.exit(2) + if len(matches) > 1: + print "%s matched multiple actions:" % action + for k, v in matches: + print "\t%s" % k + sys.exit(2) + action, fn = matches[0] + # call the action with the remaining arguments + try: + fn(*argv) + except TypeError: + print "Wrong number of arguments supplied" + print "%s %s: %s" % (category, action, fn.__doc__) + diff --git a/bin/nova-objectstore b/bin/nova-objectstore new file mode 100755 index 000000000..38a23f1ff --- /dev/null +++ b/bin/nova-objectstore @@ -0,0 +1,49 @@ +#!/usr/bin/env python +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright [2010] [Anso Labs, 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. +""" + Tornado daemon for nova objectstore. Supports S3 API. +""" + +import logging + +from nova import vendor +from tornado import httpserver +from tornado import ioloop + +from nova import flags +from nova import server +from nova import utils +from nova.auth import users +from nova.objectstore import handler + + +FLAGS = flags.FLAGS + + +def main(argv): + # FIXME: if this log statement isn't here, no logging + # appears from other files and app won't start daemonized + logging.debug('Started HTTP server on %s' % (FLAGS.s3_internal_port)) + app = handler.Application(users.UserManager()) + server = httpserver.HTTPServer(app) + server.listen(FLAGS.s3_internal_port) + ioloop.IOLoop.instance().start() + + +if __name__ == '__main__': + utils.default_flagfile() + server.serve('nova-objectstore', main) diff --git a/bin/nova-volume b/bin/nova-volume new file mode 100755 index 000000000..e36954cd3 --- /dev/null +++ b/bin/nova-volume @@ -0,0 +1,68 @@ +#!/usr/bin/env python +# vim: tabstop=4 shiftwidth=4 softtabstop + +# Copyright [2010] [Anso Labs, 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. +""" + Tornado Storage daemon manages AoE volumes via AMQP messaging. +""" + +import logging + +from nova import vendor +from tornado import ioloop + +from nova import flags +from nova import rpc +from nova import server +from nova import utils +from nova.volume import storage + + +FLAGS = flags.FLAGS +flags.DEFINE_integer('storage_report_state_interval', 10, + 'seconds between broadcasting state to cloud', + lower_bound=1) + + +def main(argv): + bs = storage.BlockStore() + + conn = rpc.Connection.instance() + consumer_all = rpc.AdapterConsumer( + connection=conn, + topic='%s' % FLAGS.storage_topic, + proxy=bs) + + consumer_node = rpc.AdapterConsumer( + connection=conn, + topic='%s.%s' % (FLAGS.storage_topic, FLAGS.node_name), + proxy=bs) + + io_inst = ioloop.IOLoop.instance() + scheduler = ioloop.PeriodicCallback( + lambda: bs.report_state(), + FLAGS.storage_report_state_interval * 1000, + io_loop=io_inst) + + injected = consumer_all.attachToTornado(io_inst) + injected = consumer_node.attachToTornado(io_inst) + scheduler.start() + io_inst.start() + + +if __name__ == '__main__': + utils.default_flagfile() + server.serve('nova-volume', main) + |
