summaryrefslogtreecommitdiffstats
path: root/bin
diff options
context:
space:
mode:
authorJesse Andrews <anotherjesse@gmail.com>2010-05-27 23:05:26 -0700
committerJesse Andrews <anotherjesse@gmail.com>2010-05-27 23:05:26 -0700
commitbf6e6e718cdc7488e2da87b21e258ccc065fe499 (patch)
tree51cf4f72047eb6b16079c7fe21e9822895541801 /bin
downloadnova-bf6e6e718cdc7488e2da87b21e258ccc065fe499.tar.gz
nova-bf6e6e718cdc7488e2da87b21e258ccc065fe499.tar.xz
nova-bf6e6e718cdc7488e2da87b21e258ccc065fe499.zip
initial commit
Diffstat (limited to 'bin')
-rwxr-xr-xbin/nova-api63
-rwxr-xr-xbin/nova-compute97
-rwxr-xr-xbin/nova-manage158
-rwxr-xr-xbin/nova-objectstore49
-rwxr-xr-xbin/nova-volume68
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)
+