summaryrefslogtreecommitdiffstats
path: root/bin
diff options
context:
space:
mode:
authorVishvananda Ishaya <vishvananda@gmail.com>2011-01-18 12:42:06 -0800
committerVishvananda Ishaya <vishvananda@gmail.com>2011-01-18 12:42:06 -0800
commitef9b60f4b8d22f16c0606c5b3c2d2d40d76eac02 (patch)
treecd0edbb59607c2b4c68301e3e45efc37dc30da54 /bin
parent47a2dc24b08ca4be7d114d95b42dc4faf19d9fad (diff)
parent4577c11923f05ba60ec898186d3f959d86e5de4c (diff)
downloadnova-ef9b60f4b8d22f16c0606c5b3c2d2d40d76eac02.tar.gz
nova-ef9b60f4b8d22f16c0606c5b3c2d2d40d76eac02.tar.xz
nova-ef9b60f4b8d22f16c0606c5b3c2d2d40d76eac02.zip
merged trunk
Diffstat (limited to 'bin')
-rwxr-xr-xbin/nova-api51
-rwxr-xr-xbin/nova-api-paste109
-rwxr-xr-xbin/nova-combined29
-rwxr-xr-xbin/nova-direct-api61
-rwxr-xr-xbin/nova-manage82
-rwxr-xr-xbin/stack145
6 files changed, 349 insertions, 128 deletions
diff --git a/bin/nova-api b/bin/nova-api
index c7cbb3ab4..7b4fbeab1 100755
--- a/bin/nova-api
+++ b/bin/nova-api
@@ -34,22 +34,53 @@ if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')):
gettext.install('nova', unicode=1)
-from nova import api
from nova import flags
-from nova import utils
+from nova import log as logging
from nova import wsgi
+logging.basicConfig()
+LOG = logging.getLogger('nova.api')
+LOG.setLevel(logging.DEBUG)
FLAGS = flags.FLAGS
-flags.DEFINE_string('osapi_host', '0.0.0.0', 'OpenStack API host')
-flags.DEFINE_integer('ec2api_port', 8773, 'EC2 API port')
-flags.DEFINE_string('ec2api_host', '0.0.0.0', 'EC2 API host')
+API_ENDPOINTS = ['ec2', 'osapi']
-if __name__ == '__main__':
- utils.default_flagfile()
- FLAGS(sys.argv)
+
+def run_app(paste_config_file):
+ LOG.debug(_("Using paste.deploy config at: %s"), paste_config_file)
+ apps = []
+ for api in API_ENDPOINTS:
+ config = wsgi.load_paste_configuration(paste_config_file, api)
+ if config is None:
+ LOG.debug(_("No paste configuration for app: %s"), api)
+ continue
+ LOG.debug(_("App Config: %s\n%r"), api, config)
+ wsgi.paste_config_to_flags(config, {
+ "verbose": FLAGS.verbose,
+ "%s_host" % api: config.get('host', '0.0.0.0'),
+ "%s_port" % api: getattr(FLAGS, "%s_port" % api)})
+ LOG.info(_("Running %s API"), api)
+ app = wsgi.load_paste_app(paste_config_file, api)
+ apps.append((app, getattr(FLAGS, "%s_port" % api),
+ getattr(FLAGS, "%s_host" % api)))
+ if len(apps) == 0:
+ LOG.error(_("No known API applications configured in %s."),
+ paste_config_file)
+ return
+
+ # NOTE(todd): redo logging config, verbose could be set in paste config
+ logging.basicConfig()
server = wsgi.Server()
- server.start(api.API('os'), FLAGS.osapi_port, host=FLAGS.osapi_host)
- server.start(api.API('ec2'), FLAGS.ec2api_port, host=FLAGS.ec2api_host)
+ for app in apps:
+ server.start(*app)
server.wait()
+
+
+if __name__ == '__main__':
+ FLAGS(sys.argv)
+ conf = wsgi.paste_config_file('nova-api.conf')
+ if conf:
+ run_app(conf)
+ else:
+ LOG.error(_("No paste configuration found for: %s"), 'nova-api.conf')
diff --git a/bin/nova-api-paste b/bin/nova-api-paste
deleted file mode 100755
index 419f0bbdc..000000000
--- a/bin/nova-api-paste
+++ /dev/null
@@ -1,109 +0,0 @@
-#!/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 API."""
-
-import gettext
-import os
-import sys
-
-from paste import deploy
-
-# 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 log as logging
-from nova import wsgi
-
-LOG = logging.getLogger('nova.api')
-LOG.setLevel(logging.DEBUG)
-LOG.addHandler(logging.StreamHandler())
-
-FLAGS = flags.FLAGS
-
-API_ENDPOINTS = ['ec2', 'openstack']
-
-
-def load_configuration(paste_config):
- """Load the paste configuration from the config file and return it."""
- config = None
- # Try each known name to get the global DEFAULTS, which will give ports
- for name in API_ENDPOINTS:
- try:
- config = deploy.appconfig("config:%s" % paste_config, name=name)
- except LookupError:
- pass
- if config:
- verbose = config.get('verbose', None)
- if verbose:
- FLAGS.verbose = int(verbose) == 1
- if FLAGS.verbose:
- logging.getLogger().setLevel(logging.DEBUG)
- return config
- LOG.debug(_("Paste config at %s has no secion for known apis"),
- paste_config)
- print _("Paste config at %s has no secion for any known apis") % \
- paste_config
- os.exit(1)
-
-
-def launch_api(paste_config_file, section, server, port, host):
- """Launch an api server from the specified port and IP."""
- LOG.debug(_("Launching %s api on %s:%s"), section, host, port)
- app = deploy.loadapp('config:%s' % paste_config_file, name=section)
- server.start(app, int(port), host)
-
-
-def run_app(paste_config_file):
- LOG.debug(_("Using paste.deploy config at: %s"), configfile)
- config = load_configuration(paste_config_file)
- LOG.debug(_("Configuration: %r"), config)
- server = wsgi.Server()
- ip = config.get('host', '0.0.0.0')
- for api in API_ENDPOINTS:
- port = config.get("%s_port" % api, None)
- if not port:
- continue
- host = config.get("%s_host" % api, ip)
- launch_api(configfile, api, server, port, host)
- LOG.debug(_("All api servers launched, now waiting"))
- server.wait()
-
-
-if __name__ == '__main__':
- FLAGS(sys.argv)
- configfiles = ['/etc/nova/nova-api.conf']
- if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')):
- configfiles.insert(0,
- os.path.join(possible_topdir, 'etc', 'nova-api.conf'))
- for configfile in configfiles:
- if os.path.exists(configfile):
- run_app(configfile)
- break
- else:
- LOG.debug(_("Skipping missing configuration: %s"), configfile)
diff --git a/bin/nova-combined b/bin/nova-combined
index f932fdfd5..913c866bf 100755
--- a/bin/nova-combined
+++ b/bin/nova-combined
@@ -36,22 +36,20 @@ if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')):
gettext.install('nova', unicode=1)
-from nova import api
from nova import flags
+from nova import log as logging
from nova import service
from nova import utils
from nova import wsgi
FLAGS = flags.FLAGS
-flags.DEFINE_string('osapi_host', '0.0.0.0', 'OpenStack API host')
-flags.DEFINE_integer('ec2api_port', 8773, 'EC2 API port')
-flags.DEFINE_string('ec2api_host', '0.0.0.0', 'EC2 API host')
if __name__ == '__main__':
utils.default_flagfile()
FLAGS(sys.argv)
+ logging.basicConfig()
compute = service.Service.create(binary='nova-compute')
network = service.Service.create(binary='nova-network')
@@ -61,7 +59,22 @@ if __name__ == '__main__':
service.serve(compute, network, volume, scheduler)
- server = wsgi.Server()
- server.start(api.API('os'), FLAGS.osapi_port, host=FLAGS.osapi_host)
- server.start(api.API('ec2'), FLAGS.ec2api_port, host=FLAGS.ec2api_host)
- server.wait()
+ apps = []
+ paste_config_file = wsgi.paste_config_file('nova-api.conf')
+ for api in ['osapi', 'ec2']:
+ config = wsgi.load_paste_configuration(paste_config_file, api)
+ if config is None:
+ continue
+ wsgi.paste_config_to_flags(config, {
+ "verbose": FLAGS.verbose,
+ "%s_host" % api: config.get('host', '0.0.0.0'),
+ "%s_port" % api: getattr(FLAGS, "%s_port" % api)})
+ app = wsgi.load_paste_app(paste_config_file, api)
+ apps.append((app, getattr(FLAGS, "%s_port" % api),
+ getattr(FLAGS, "%s_host" % api)))
+ if len(apps) > 0:
+ logging.basicConfig()
+ server = wsgi.Server()
+ for app in apps:
+ server.start(*app)
+ server.wait()
diff --git a/bin/nova-direct-api b/bin/nova-direct-api
new file mode 100755
index 000000000..e7dd14fb2
--- /dev/null
+++ b/bin/nova-direct-api
@@ -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 Direct 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 direct
+from nova.compute import api as compute_api
+
+
+FLAGS = flags.FLAGS
+flags.DEFINE_integer('direct_port', 8001, 'Direct API port')
+flags.DEFINE_string('direct_host', '0.0.0.0', 'Direct API host')
+
+if __name__ == '__main__':
+ utils.default_flagfile()
+ FLAGS(sys.argv)
+
+ direct.register_service('compute', compute_api.ComputeAPI())
+ direct.register_service('reflect', direct.Reflection())
+ router = direct.Router()
+ with_json = direct.JsonParamsMiddleware(router)
+ with_req = direct.PostParamsMiddleware(with_json)
+ with_auth = direct.DelegatedAuthMiddleware(with_req)
+
+ server = wsgi.Server()
+ server.start(with_auth, FLAGS.direct_port, host=FLAGS.direct_host)
+ server.wait()
diff --git a/bin/nova-manage b/bin/nova-manage
index b5842b595..1ad3120b8 100755
--- a/bin/nova-manage
+++ b/bin/nova-manage
@@ -62,6 +62,7 @@ import time
import IPy
+
# 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]),
@@ -81,8 +82,9 @@ from nova import log as logging
from nova import quota
from nova import utils
from nova.auth import manager
+from nova import rpc
from nova.cloudpipe import pipelib
-
+from nova.api.ec2 import cloud
logging.basicConfig()
FLAGS = flags.FLAGS
@@ -465,6 +467,82 @@ class NetworkCommands(object):
int(vpn_start), fixed_range_v6)
+class InstanceCommands(object):
+ """Class for mangaging VM instances."""
+
+ def live_migration(self, ec2_id, dest):
+ """live_migration"""
+
+ ctxt = context.get_admin_context()
+ instance_id = cloud.ec2_id_to_id(ec2_id)
+
+ if FLAGS.connection_type != 'libvirt':
+ msg = _('Only KVM is supported for now. Sorry!')
+ raise exception.Error(msg)
+
+ if FLAGS.volume_driver != 'nova.volume.driver.AOEDriver':
+ instance_ref = db.instance_get(ctxt, instance_id)
+ if len(instance_ref['volumes']) != 0:
+ msg = _(("""Volumes attached by ISCSIDriver"""
+ """ are not supported. Sorry!"""))
+ raise exception.Error(msg)
+
+ rpc.call(ctxt,
+ FLAGS.scheduler_topic,
+ {"method": "live_migration",
+ "args": {"instance_id": instance_id,
+ "dest": dest,
+ "topic": FLAGS.compute_topic}})
+
+ msg = 'Migration of %s initiated. ' % ec2_id
+ msg += 'Check its progress using euca-describe-instances.'
+ print msg
+
+
+class HostCommands(object):
+ """Class for mangaging host(physical nodes)."""
+
+ def list(self):
+ """describe host list."""
+
+ # To supress msg: No handlers could be found for logger "amqplib"
+ logging.basicConfig()
+
+ service_refs = db.service_get_all(context.get_admin_context())
+ hosts = [h['host'] for h in service_refs]
+ hosts = list(set(hosts))
+ for host in hosts:
+ print host
+
+ def show(self, host):
+ """describe cpu/memory/hdd info for host."""
+
+ result = rpc.call(context.get_admin_context(),
+ FLAGS.scheduler_topic,
+ {"method": "show_host_resource",
+ "args": {"host": host}})
+
+ # Checking result msg format is necessary, that will have done
+ # when this feture is included in API.
+ if type(result) != dict:
+ print 'Unexpected error occurs'
+ elif not result['ret']:
+ print '%s' % result['msg']
+ else:
+ cpu = result['phy_resource']['vcpus']
+ mem = result['phy_resource']['memory_mb']
+ hdd = result['phy_resource']['local_gb']
+
+ print 'HOST\t\tPROJECT\t\tcpu\tmem(mb)\tdisk(gb)'
+ print '%s\t\t\t%s\t%s\t%s' % (host, cpu, mem, hdd)
+ for p_id, val in result['usage'].items():
+ print '%s\t%s\t\t%s\t%s\t%s' % (host,
+ p_id,
+ val['vcpus'],
+ val['memory_mb'],
+ val['local_gb'])
+
+
class ServiceCommands(object):
"""Enable and disable running services"""
@@ -527,6 +605,8 @@ CATEGORIES = [
('vpn', VpnCommands),
('floating', FloatingIpCommands),
('network', NetworkCommands),
+ ('instance', InstanceCommands),
+ ('host', HostCommands),
('service', ServiceCommands),
('log', LogCommands)]
diff --git a/bin/stack b/bin/stack
new file mode 100755
index 000000000..7a6ce5960
--- /dev/null
+++ b/bin/stack
@@ -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 Direct 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', 'Direct API host')
+gflags.DEFINE_integer('port', 8001, 'Direct API host')
+gflags.DEFINE_string('user', 'user1', 'Direct API username')
+gflags.DEFINE_string('project', 'proj1', 'Direct 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 = x.split('=', 1)
+ params[key] = value
+
+ pprint.pprint(do_request(controller, method, params))