From 2925ca3ac3010b9a65276ad2cfc8118679827da3 Mon Sep 17 00:00:00 2001 From: masumotok Date: Tue, 7 Dec 2010 19:25:43 +0900 Subject: rev439ベースにライブマイグレーションの機能をマージ このバージョンはEBSなし、CPUフラグのチェックなし MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bin/nova-manage | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 120 insertions(+), 2 deletions(-) (limited to 'bin') diff --git a/bin/nova-manage b/bin/nova-manage index eb7c6b87b..d41ae8600 100755 --- a/bin/nova-manage +++ b/bin/nova-manage @@ -76,6 +76,13 @@ from nova import quota from nova import utils from nova.auth import manager from nova.cloudpipe import pipelib +#added by masumotok +from nova import rpc +# added by masumotok +from nova.api.ec2 import cloud +# added by masumotok +from nova.compute import power_state + FLAGS = flags.FLAGS @@ -424,6 +431,116 @@ class NetworkCommands(object): int(network_size), int(vlan_start), int(vpn_start)) +# this class is added by masumotok +class InstanceCommands(object): + """Class for mangaging VM instances.""" + + def live_migration(self, ec2_id, dest): + """live_migration""" + + logging.basicConfig() + ctxt = context.get_admin_context() + + if 'nova.network.manager.VlanManager' != FLAGS.network_manager : + msg = 'Only nova.network.manager.VlanManager is supported now. Sorry!' + raise Exception(msg) + + # 1. whether destination host exists + host_ref = db.host_get_by_name(ctxt, dest) + + # 2. whether instance exists and running + # try-catch clause is necessary because only internal_id is shown + # when NotFound exception occurs. it isnot understandable to admins. + try : + internal_id = cloud.ec2_id_to_internal_id(ec2_id) + instance_ref = db.instance_get_by_internal_id(ctxt, internal_id) + except exception.NotFound : + print 'Not found instance_id(%s (internal_id:%s))' % ( ec2_id, internal_id) + raise + + if power_state.RUNNING != instance_ref['state'] or \ + 'running' != instance_ref['state_description']: + print 'Instance(%s) is not running' % ec2_id + sys.exit(1) + + # 3. the host where instance is running and dst host is not same + if dest == instance_ref['host'] : + print '%s is where %s is running now. choose different host.' \ + % (dest, ec2_id) + sys.exit(2) + + # 4. live migration + rpc.cast(ctxt, + FLAGS.scheduler_topic, + { "method": "live_migration", + "args": {"ec2_id": ec2_id, + "dest":dest}}) + + print 'Finished all procedure. check instance are migrated successfully' + print 'chech status by using euca-describe-instances.' + + +# this class is created by masumotok +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() + + host_refs = db.host_get_all(context.get_admin_context()) + for host_ref in host_refs: + print host_ref['name'] + + def show(self, host): + """describe cpu/memory/hdd info for host.""" + + # to supress msg: No handlers could be found for logger "amqplib" + logging.basicConfig() + + result = rpc.call(context.get_admin_context(), + FLAGS.scheduler_topic, + {"method": "show_host_resource", + "args": {"host": host}}) + + # checing result msg format is necessary, that will have done + # when this feture is included in API. + if dict != type(result): + print 'Unexpected error occurs' + elif not result['ret'] : + print '%s' % result['msg'] + else : + cpu = result['phy_resource']['cpu'] + mem = result['phy_resource']['memory_mb'] + hdd = result['phy_resource']['hdd_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['cpu'], + val['memory_mb'], + val['hdd_gb']) + + def has_keys(self, dic, keys): + not_found = [ key for key in keys if not dict.has_key(key) ] + return ( (0 == len(not_found)), not_found ) + + + +# modified by masumotok +#CATEGORIES = [ +# ('user', UserCommands), +# ('project', ProjectCommands), +# ('role', RoleCommands), +# ('shell', ShellCommands), +# ('vpn', VpnCommands), +# ('floating', FloatingIpCommands), +# ('network', NetworkCommands)] CATEGORIES = [ ('user', UserCommands), ('project', ProjectCommands), @@ -431,8 +548,9 @@ CATEGORIES = [ ('shell', ShellCommands), ('vpn', VpnCommands), ('floating', FloatingIpCommands), - ('network', NetworkCommands)] - + ('network', NetworkCommands), + ('instance', InstanceCommands), + ('host',HostCommands)] def lazy_match(name, key_value_tuples): """Finds all objects that have a key that case insensitively contains -- cgit From 4809c1bf82130f969614a8f0458636a462b81a88 Mon Sep 17 00:00:00 2001 From: masumotok Date: Thu, 16 Dec 2010 18:20:04 +0900 Subject: Hostテーブルのカラム名を修正 FlatManager, FlatDHCPManagerに対応 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bin/nova-manage | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'bin') diff --git a/bin/nova-manage b/bin/nova-manage index d41ae8600..d1cda72b7 100755 --- a/bin/nova-manage +++ b/bin/nova-manage @@ -441,10 +441,6 @@ class InstanceCommands(object): logging.basicConfig() ctxt = context.get_admin_context() - if 'nova.network.manager.VlanManager' != FLAGS.network_manager : - msg = 'Only nova.network.manager.VlanManager is supported now. Sorry!' - raise Exception(msg) - # 1. whether destination host exists host_ref = db.host_get_by_name(ctxt, dest) @@ -513,18 +509,18 @@ class HostCommands(object): elif not result['ret'] : print '%s' % result['msg'] else : - cpu = result['phy_resource']['cpu'] + cpu = result['phy_resource']['vcpus'] mem = result['phy_resource']['memory_mb'] - hdd = result['phy_resource']['hdd_gb'] + 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['cpu'], + val['vcpus'], val['memory_mb'], - val['hdd_gb']) + val['local_gb']) def has_keys(self, dic, keys): not_found = [ key for key in keys if not dict.has_key(key) ] -- cgit From f983884dd262f46907f80a04121d957347881240 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 24 Dec 2010 15:09:05 +0900 Subject: nova.compute.managerがこれまでの修正でデグレしていたので修正 CPUID, その他のチェックルーチンをnova.scheduler.manager.live_migrationに追加 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bin/nova-manage | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'bin') diff --git a/bin/nova-manage b/bin/nova-manage index d1cda72b7..d6aa29679 100755 --- a/bin/nova-manage +++ b/bin/nova-manage @@ -456,24 +456,25 @@ class InstanceCommands(object): if power_state.RUNNING != instance_ref['state'] or \ 'running' != instance_ref['state_description']: - print 'Instance(%s) is not running' % ec2_id - sys.exit(1) + raise exception.Invalid('Instance(%s) is not running' % ec2_id) # 3. the host where instance is running and dst host is not same if dest == instance_ref['host'] : - print '%s is where %s is running now. choose different host.' \ - % (dest, ec2_id) - sys.exit(2) + msg = '%s is where %s is running now. choose other host.' % (dest, ec2_id) + raise exception.Invalid(msg) # 4. live migration - rpc.cast(ctxt, - FLAGS.scheduler_topic, - { "method": "live_migration", - "args": {"ec2_id": ec2_id, - "dest":dest}}) + ret = rpc.call(ctxt, + FLAGS.scheduler_topic, + { "method": "live_migration", + "args": {"ec2_id": ec2_id, + "dest":dest}}) + + if None != ret : + raise ret print 'Finished all procedure. check instance are migrated successfully' - print 'chech status by using euca-describe-instances.' + print 'check status by using euca-describe-instances.' # this class is created by masumotok -- cgit From 8e1b74aa1c5a2f9113473eedc8e35b38b41445ea Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Mon, 27 Dec 2010 15:15:24 -0800 Subject: Added stack command-line tool --- bin/nova-easy-api | 61 +++++++++++++++++++++++ bin/stack | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 206 insertions(+) create mode 100755 bin/nova-easy-api create mode 100755 bin/stack (limited to 'bin') diff --git a/bin/nova-easy-api b/bin/nova-easy-api new file mode 100755 index 000000000..e8e86b4fb --- /dev/null +++ b/bin/nova-easy-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 Easy 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 easy +from nova.compute import api as compute_api + + +FLAGS = flags.FLAGS +flags.DEFINE_integer('easy_port', 8001, 'Easy API port') +flags.DEFINE_string('easy_host', '0.0.0.0', 'Easy API host') + +if __name__ == '__main__': + utils.default_flagfile() + FLAGS(sys.argv) + + easy.register_service('compute', compute_api.ComputeAPI()) + easy.register_service('reflect', easy.Reflection()) + router = easy.SundayMorning() + with_json = easy.JsonParamsMiddleware(router) + with_req = easy.ReqParamsMiddleware(with_json) + with_auth = easy.DelegatedAuthMiddleware(with_req) + + server = wsgi.Server() + server.start(with_auth, FLAGS.easy_port, host=FLAGS.easy_host) + server.wait() diff --git a/bin/stack b/bin/stack new file mode 100755 index 000000000..284dbf4fc --- /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 Easy 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', 'Easy API host') +gflags.DEFINE_integer('port', 8001, 'Easy API host') +gflags.DEFINE_string('user', 'user1', 'Easy API username') +gflags.DEFINE_string('project', 'proj1', 'Easy API project') + + +USAGE = """usage: stack [options] [arg1=value arg2=value] + + `stack help` should output the list of available controllers + `stack ` should output the available methods for that controller + `stack help ` should do the same + `stack help ` 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 = args.split('=', 1) + params[key] = value + + pprint.pprint(do_request(controller, method, params)) -- cgit From 35d3050511ef513ff440fbd9f8b44695ea8be797 Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Tue, 4 Jan 2011 14:07:46 -0800 Subject: rename Easy API to Direct API --- bin/nova-direct-api | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++ bin/nova-easy-api | 61 ----------------------------------------------------- 2 files changed, 61 insertions(+), 61 deletions(-) create mode 100755 bin/nova-direct-api delete mode 100755 bin/nova-easy-api (limited to 'bin') diff --git a/bin/nova-direct-api b/bin/nova-direct-api new file mode 100755 index 000000000..43046e6c2 --- /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 Easy 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-easy-api b/bin/nova-easy-api deleted file mode 100755 index e8e86b4fb..000000000 --- a/bin/nova-easy-api +++ /dev/null @@ -1,61 +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 Easy 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 easy -from nova.compute import api as compute_api - - -FLAGS = flags.FLAGS -flags.DEFINE_integer('easy_port', 8001, 'Easy API port') -flags.DEFINE_string('easy_host', '0.0.0.0', 'Easy API host') - -if __name__ == '__main__': - utils.default_flagfile() - FLAGS(sys.argv) - - easy.register_service('compute', compute_api.ComputeAPI()) - easy.register_service('reflect', easy.Reflection()) - router = easy.SundayMorning() - with_json = easy.JsonParamsMiddleware(router) - with_req = easy.ReqParamsMiddleware(with_json) - with_auth = easy.DelegatedAuthMiddleware(with_req) - - server = wsgi.Server() - server.start(with_auth, FLAGS.easy_port, host=FLAGS.easy_host) - server.wait() -- cgit From 1a66771aaf49d16d4131a1a787a1fda39aa680fd Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Tue, 4 Jan 2011 14:37:04 -0800 Subject: fix typo in stack tool --- bin/stack | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bin') diff --git a/bin/stack b/bin/stack index 284dbf4fc..42feacd63 100755 --- a/bin/stack +++ b/bin/stack @@ -139,7 +139,7 @@ if __name__ == '__main__': method = args.pop(0) params = {} for x in args: - key, value = args.split('=', 1) + key, value = x.split('=', 1) params[key] = value pprint.pprint(do_request(controller, method, params)) -- cgit From 5679caa48b90ecebf9a1143bf92cec0e7c0ed1f8 Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Tue, 4 Jan 2011 14:39:48 -0800 Subject: rename easy to direct in the scripts --- bin/nova-direct-api | 2 +- bin/stack | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'bin') diff --git a/bin/nova-direct-api b/bin/nova-direct-api index 43046e6c2..e7dd14fb2 100755 --- a/bin/nova-direct-api +++ b/bin/nova-direct-api @@ -18,7 +18,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""Starter script for Nova Easy API.""" +"""Starter script for Nova Direct API.""" import gettext import os diff --git a/bin/stack b/bin/stack index 42feacd63..7a6ce5960 100755 --- a/bin/stack +++ b/bin/stack @@ -17,7 +17,7 @@ # License for the specific language governing permissions and limitations # under the License. -"""CLI for the Easy API.""" +"""CLI for the Direct API.""" import eventlet eventlet.monkey_patch() @@ -42,10 +42,10 @@ from nova import utils FLAGS = gflags.FLAGS -gflags.DEFINE_string('host', '127.0.0.1', 'Easy API host') -gflags.DEFINE_integer('port', 8001, 'Easy API host') -gflags.DEFINE_string('user', 'user1', 'Easy API username') -gflags.DEFINE_string('project', 'proj1', 'Easy API project') +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] [arg1=value arg2=value] -- cgit From 2491c2484f025cb3f061fcc6a5c6915006feb47b Mon Sep 17 00:00:00 2001 From: Todd Willey Date: Tue, 4 Jan 2011 18:16:16 -0500 Subject: Make paste the default api pattern. * get rid of the --use_lockout flag since it will be specified in paste config (Example line is commented out in etc/nova-api.conf, factory is in place) * remove old nova-api binary and promote nova-api-paste * change how we store ec2 parameters to bin the the ApiRequest * get rid of Router, since paste.urlmap is equally effective (Requestify now gets passed the name of the controller requests are to.) --- bin/nova-api | 75 ++++++++++++++++++++++++++++++------ bin/nova-api-paste | 109 ----------------------------------------------------- 2 files changed, 64 insertions(+), 120 deletions(-) delete mode 100755 bin/nova-api-paste (limited to 'bin') diff --git a/bin/nova-api b/bin/nova-api index 1c671201e..6ee833a18 100755 --- a/bin/nova-api +++ b/bin/nova-api @@ -21,9 +21,12 @@ """Starter script for Nova API.""" import gettext +import logging 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]), @@ -34,23 +37,73 @@ 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 wsgi +LOG = logging.getLogger('nova.api') +LOG.setLevel(logging.DEBUG) +LOG.addHandler(logging.StreamHandler()) FLAGS = flags.FLAGS -flags.DEFINE_integer('osapi_port', 8774, 'OpenStack API port') -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', 'openstack'] -if __name__ == '__main__': - utils.default_flagfile() - FLAGS(sys.argv) + +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() - server.start(api.API('os'), FLAGS.osapi_port, host=FLAGS.osapi_host) - server.start(api.API('ec2'), FLAGS.ec2api_port, host=FLAGS.ec2api_host) + 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-api-paste b/bin/nova-api-paste deleted file mode 100755 index 6ee833a18..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 logging -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 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) -- cgit From 5afd9848ad09414c00062ceebdad45bca0604888 Mon Sep 17 00:00:00 2001 From: Muneyuki Noguchi Date: Tue, 11 Jan 2011 18:01:23 +0900 Subject: Add support for EBS volumes to the live migration feature. Currently, only AoE is supported. --- bin/nova-manage | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'bin') diff --git a/bin/nova-manage b/bin/nova-manage index 7c87d21ff..fa044859d 100755 --- a/bin/nova-manage +++ b/bin/nova-manage @@ -83,8 +83,6 @@ from nova import rpc from nova.cloudpipe import pipelib from nova.api.ec2 import cloud - - FLAGS = flags.FLAGS flags.DECLARE('fixed_range', 'nova.network.manager') flags.DECLARE('num_networks', 'nova.network.manager') @@ -462,6 +460,10 @@ class InstanceCommands(object): def live_migration(self, ec2_id, dest): """live_migration""" + if FLAGS.volume_driver != 'nova.volume.driver.AOEDriver': + raise exception.Error('Only AOEDriver is supported for now. ' + 'Sorry.') + logging.basicConfig() ctxt = context.get_admin_context() @@ -491,7 +493,6 @@ class InstanceCommands(object): class HostCommands(object): """Class for mangaging host(physical nodes).""" - def list(self): """describe host list.""" @@ -502,7 +503,6 @@ class HostCommands(object): for host_ref in host_refs: print host_ref['name'] - def show(self, host): """describe cpu/memory/hdd info for host.""" @@ -546,6 +546,7 @@ CATEGORIES = [ ('instance', InstanceCommands), ('host', HostCommands)] + 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) -- cgit From c57ccba743c54786e28317194000bcf22dc5b69e Mon Sep 17 00:00:00 2001 From: Kei Masumoto Date: Fri, 14 Jan 2011 08:26:25 +0900 Subject: checking based on pep8 --- bin/nova-manage | 1 - 1 file changed, 1 deletion(-) (limited to 'bin') diff --git a/bin/nova-manage b/bin/nova-manage index fb6b06694..b8a181343 100755 --- a/bin/nova-manage +++ b/bin/nova-manage @@ -468,7 +468,6 @@ class InstanceCommands(object): def live_migration(self, ec2_id, dest): """live_migration""" - if FLAGS.connection_type != 'libvirt': raise exception.Error('Only KVM is supported for now. ' 'Sorry.') -- cgit From 525544e689334346305ecc11552105fc1b32a5dd Mon Sep 17 00:00:00 2001 From: Kei Masumoto Date: Sun, 16 Jan 2011 14:54:35 +0900 Subject: merged to rev 561 and fixed based on reviewer's comment --- bin/nova-manage | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'bin') diff --git a/bin/nova-manage b/bin/nova-manage index b8a181343..6bd6aef64 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]), @@ -468,17 +469,19 @@ class InstanceCommands(object): 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': - raise exception.Error('Only KVM is supported for now. ' - 'Sorry.') + msg = _('Only KVM is supported for now. Sorry!') + raise exception.Error(msg) if FLAGS.volume_driver != 'nova.volume.driver.AOEDriver': - raise exception.Error('Only AOEDriver is supported for now. ' - 'Sorry.') - - logging.basicConfig() - ctxt = context.get_admin_context() - instance_id = cloud.ec2_id_to_id(ec2_id) + instance_ref = db.instance_get(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, @@ -501,16 +504,15 @@ class HostCommands(object): # To supress msg: No handlers could be found for logger "amqplib" logging.basicConfig() - host_refs = db.host_get_all(context.get_admin_context()) - for host_ref in host_refs: - print host_ref['name'] + 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.""" - # To supress msg: No handlers could be found for logger "amqplib" - logging.basicConfig() - result = rpc.call(context.get_admin_context(), FLAGS.scheduler_topic, {"method": "show_host_resource", -- cgit