diff --git a/Authors b/Authors index 82e07a6b..608fec52 100644 --- a/Authors +++ b/Authors @@ -40,6 +40,7 @@ Nachi Ueno Rick Clark Rick Harris +Rob Kost Ryan Lane Ryan Lucio Salvatore Orlando diff --git a/MANIFEST.in b/MANIFEST.in index 07e4dd51..3908830d 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -5,6 +5,7 @@ graft CA graft doc graft smoketests graft tools +graft etc include nova/api/openstack/notes.txt include nova/auth/novarc.template include nova/auth/slap.sh diff --git a/bin/nova-api b/bin/nova-api index 7b4fbeab..44bbfaf8 100755 --- a/bin/nova-api +++ b/bin/nova-api @@ -36,6 +36,7 @@ gettext.install('nova', unicode=1) from nova import flags from nova import log as logging +from nova import version from nova import wsgi logging.basicConfig() @@ -79,6 +80,8 @@ def run_app(paste_config_file): if __name__ == '__main__': FLAGS(sys.argv) + LOG.audit(_("Starting nova-api node (version %s)"), + version.version_string_with_vcs()) conf = wsgi.paste_config_file('nova-api.conf') if conf: run_app(conf) diff --git a/bin/nova-direct-api b/bin/nova-direct-api index e7dd14fb..173b39bd 100755 --- a/bin/nova-direct-api +++ b/bin/nova-direct-api @@ -49,7 +49,7 @@ if __name__ == '__main__': utils.default_flagfile() FLAGS(sys.argv) - direct.register_service('compute', compute_api.ComputeAPI()) + direct.register_service('compute', compute_api.API()) direct.register_service('reflect', direct.Reflection()) router = direct.Router() with_json = direct.JsonParamsMiddleware(router) diff --git a/bin/nova-manage b/bin/nova-manage index 70355a59..7f671131 100755 --- a/bin/nova-manage +++ b/bin/nova-manage @@ -79,7 +79,9 @@ from nova import exception from nova import flags from nova import log as logging from nova import quota +from nova import rpc from nova import utils +from nova.api.ec2.cloud import ec2_id_to_id from nova.auth import manager from nova.cloudpipe import pipelib from nova.db import migration @@ -95,6 +97,16 @@ flags.DECLARE('vpn_start', 'nova.network.manager') flags.DECLARE('fixed_range_v6', 'nova.network.manager') +def param2id(object_id): + """Helper function to convert various id types to internal id. + args: [object_id], e.g. 'vol-0000000a' or 'volume-0000000a' or '10' + """ + if '-' in object_id: + return ec2_id_to_id(object_id) + else: + return int(object_id) + + class VpnCommands(object): """Class for managing VPNs.""" @@ -553,6 +565,46 @@ class DbCommands(object): print migration.db_version() +class VolumeCommands(object): + """Methods for dealing with a cloud in an odd state""" + + def delete(self, volume_id): + """Delete a volume, bypassing the check that it + must be available. + args: volume_id_id""" + ctxt = context.get_admin_context() + volume = db.volume_get(ctxt, param2id(volume_id)) + host = volume['host'] + if volume['status'] == 'in-use': + print "Volume is in-use." + print "Detach volume from instance and then try again." + return + + rpc.cast(ctxt, + db.queue_get_for(ctxt, FLAGS.volume_topic, host), + {"method": "delete_volume", + "args": {"volume_id": volume['id']}}) + + def reattach(self, volume_id): + """Re-attach a volume that has previously been attached + to an instance. Typically called after a compute host + has been rebooted. + args: volume_id_id""" + ctxt = context.get_admin_context() + volume = db.volume_get(ctxt, param2id(volume_id)) + if not volume['instance_id']: + print "volume is not attached to an instance" + return + instance = db.instance_get(ctxt, volume['instance_id']) + host = instance['host'] + rpc.cast(ctxt, + db.queue_get_for(ctxt, FLAGS.compute_topic, host), + {"method": "attach_volume", + "args": {"instance_id": instance['id'], + "volume_id": volume['id'], + "mountpoint": volume['mountpoint']}}) + + CATEGORIES = [ ('user', UserCommands), ('project', ProjectCommands), @@ -563,7 +615,8 @@ CATEGORIES = [ ('network', NetworkCommands), ('service', ServiceCommands), ('log', LogCommands), - ('db', DbCommands)] + ('db', DbCommands), + ('volume', VolumeCommands)] def lazy_match(name, key_value_tuples): diff --git a/bin/stack b/bin/stack index 7a6ce596..25caca06 100755 --- a/bin/stack +++ b/bin/stack @@ -22,6 +22,7 @@ import eventlet eventlet.monkey_patch() +import json import os import pprint import sys @@ -38,7 +39,6 @@ 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 @@ -106,8 +106,12 @@ def do_request(controller, method, params=None): 'X-OpenStack-Project': FLAGS.project} req = urllib2.Request(url, data, headers) - resp = urllib2.urlopen(req) - return utils.loads(resp.read()) + try: + resp = urllib2.urlopen(req) + except urllib2.HTTPError, e: + print e.read() + sys.exit(1) + return json.loads(resp.read()) if __name__ == '__main__': diff --git a/nova/auth/dbdriver.py b/nova/auth/dbdriver.py index 0eb6fe58..d8dad8ed 100644 --- a/nova/auth/dbdriver.py +++ b/nova/auth/dbdriver.py @@ -119,8 +119,8 @@ class DbDriver(object): for member_uid in member_uids: member = db.user_get(context.get_admin_context(), member_uid) if not member: - raise exception.NotFound("Project can't be created " - "because user %s doesn't exist" + raise exception.NotFound(_("Project can't be created " + "because user %s doesn't exist") % member_uid) members.add(member) diff --git a/nova/auth/ldapdriver.py b/nova/auth/ldapdriver.py index bc53e0ec..a6915ce0 100644 --- a/nova/auth/ldapdriver.py +++ b/nova/auth/ldapdriver.py @@ -146,7 +146,7 @@ class LdapDriver(object): def create_user(self, name, access_key, secret_key, is_admin): """Create a user""" if self.__user_exists(name): - raise exception.Duplicate("LDAP user %s already exists" % name) + raise exception.Duplicate(_("LDAP user %s already exists") % name) if FLAGS.ldap_user_modify_only: if self.__ldap_user_exists(name): # Retrieve user by name @@ -310,7 +310,7 @@ class LdapDriver(object): def delete_user(self, uid): """Delete a user""" if not self.__user_exists(uid): - raise exception.NotFound("User %s doesn't exist" % uid) + raise exception.NotFound(_("User %s doesn't exist") % uid) self.__remove_from_all(uid) if FLAGS.ldap_user_modify_only: # Delete attributes @@ -432,15 +432,15 @@ class LdapDriver(object): description, member_uids=None): """Create a group""" if self.__group_exists(group_dn): - raise exception.Duplicate("Group can't be created because " - "group %s already exists" % name) + raise exception.Duplicate(_("Group can't be created because " + "group %s already exists") % name) members = [] if member_uids is not None: for member_uid in member_uids: if not self.__user_exists(member_uid): - raise exception.NotFound("Group can't be created " - "because user %s doesn't exist" % - member_uid) + raise exception.NotFound(_("Group can't be created " + "because user %s doesn't exist") + % member_uid) members.append(self.__uid_to_dn(member_uid)) dn = self.__uid_to_dn(uid) if not dn in members: @@ -455,8 +455,8 @@ class LdapDriver(object): def __is_in_group(self, uid, group_dn): """Check if user is in group""" if not self.__user_exists(uid): - raise exception.NotFound("User %s can't be searched in group " - "because the user doesn't exist" % uid) + raise exception.NotFound(_("User %s can't be searched in group " + "because the user doesn't exist") % uid) if not self.__group_exists(group_dn): return False res = self.__find_object(group_dn, @@ -467,10 +467,10 @@ class LdapDriver(object): def __add_to_group(self, uid, group_dn): """Add user to group""" if not self.__user_exists(uid): - raise exception.NotFound("User %s can't be added to the group " - "because the user doesn't exist" % uid) + raise exception.NotFound(_("User %s can't be added to the group " + "because the user doesn't exist") % uid) if not self.__group_exists(group_dn): - raise exception.NotFound("The group at dn %s doesn't exist" % + raise exception.NotFound(_("The group at dn %s doesn't exist") % group_dn) if self.__is_in_group(uid, group_dn): raise exception.Duplicate(_("User %s is already a member of " @@ -481,15 +481,15 @@ class LdapDriver(object): def __remove_from_group(self, uid, group_dn): """Remove user from group""" if not self.__group_exists(group_dn): - raise exception.NotFound("The group at dn %s doesn't exist" % - group_dn) + raise exception.NotFound(_("The group at dn %s doesn't exist") + % group_dn) if not self.__user_exists(uid): - raise exception.NotFound("User %s can't be removed from the " - "group because the user doesn't exist" % - uid) + raise exception.NotFound(_("User %s can't be removed from the " + "group because the user doesn't exist") + % uid) if not self.__is_in_group(uid, group_dn): - raise exception.NotFound("User %s is not a member of the group" % - uid) + raise exception.NotFound(_("User %s is not a member of the group") + % uid) # NOTE(vish): remove user from group and any sub_groups sub_dns = self.__find_group_dns_with_member(group_dn, uid) for sub_dn in sub_dns: @@ -509,8 +509,9 @@ class LdapDriver(object): def __remove_from_all(self, uid): """Remove user from all roles and projects""" if not self.__user_exists(uid): - raise exception.NotFound("User %s can't be removed from all " - "because the user doesn't exist" % uid) + raise exception.NotFound(_("User %s can't be removed from all " + "because the user doesn't exist") + % uid) role_dns = self.__find_group_dns_with_member( FLAGS.role_project_subtree, uid) for role_dn in role_dns: diff --git a/nova/log.py b/nova/log.py index 4997d3f2..e1c9f46f 100644 --- a/nova/log.py +++ b/nova/log.py @@ -40,15 +40,15 @@ from nova import version FLAGS = flags.FLAGS flags.DEFINE_string('logging_context_format_string', - '(%(name)s %(nova_version)s): %(levelname)s ' + '%(asctime)s %(levelname)s %(name)s ' '[%(request_id)s %(user)s ' '%(project)s] %(message)s', - 'format string to use for log messages') + 'format string to use for log messages with context') flags.DEFINE_string('logging_default_format_string', - '(%(name)s %(nova_version)s): %(levelname)s [N/A] ' + '%(asctime)s %(levelname)s %(name)s [-] ' '%(message)s', - 'format string to use for log messages') + 'format string to use for log messages without context') flags.DEFINE_string('logging_debug_format_suffix', 'from %(processName)s (pid=%(process)d) %(funcName)s' diff --git a/nova/rpc.py b/nova/rpc.py index 49b11602..bbfa7113 100644 --- a/nova/rpc.py +++ b/nova/rpc.py @@ -343,7 +343,7 @@ def call(context, topic, msg): def cast(context, topic, msg): """Sends a message on a topic without waiting for a response""" - LOG.debug("Making asynchronous cast...") + LOG.debug(_("Making asynchronous cast...")) _pack_context(msg, context) conn = Connection.instance() publisher = TopicPublisher(connection=conn, topic=topic) diff --git a/nova/scheduler/simple.py b/nova/scheduler/simple.py index 47baf0d7..baf4966d 100644 --- a/nova/scheduler/simple.py +++ b/nova/scheduler/simple.py @@ -48,7 +48,7 @@ class SimpleScheduler(chance.ChanceScheduler): service = db.service_get_by_args(context.elevated(), host, 'nova-compute') if not self.service_is_up(service): - raise driver.WillNotSchedule("Host %s is not alive" % host) + raise driver.WillNotSchedule(_("Host %s is not alive") % host) # TODO(vish): this probably belongs in the manager, if we # can generalize this somehow @@ -80,7 +80,7 @@ class SimpleScheduler(chance.ChanceScheduler): service = db.service_get_by_args(context.elevated(), host, 'nova-volume') if not self.service_is_up(service): - raise driver.WillNotSchedule("Host %s not available" % host) + raise driver.WillNotSchedule(_("Host %s not available") % host) # TODO(vish): this probably belongs in the manager, if we # can generalize this somehow diff --git a/nova/twistd.py b/nova/twistd.py index 55627199..6390a814 100644 --- a/nova/twistd.py +++ b/nova/twistd.py @@ -156,7 +156,7 @@ def WrapTwistedOptions(wrapped): try: self.parseArgs(*argv) except TypeError: - raise usage.UsageError("Wrong number of arguments.") + raise usage.UsageError(_("Wrong number of arguments.")) self.postOptions() return args @@ -220,7 +220,7 @@ def stop(pidfile): time.sleep(0.1) except OSError, err: err = str(err) - if err.find("No such process") > 0: + if err.find(_("No such process")) > 0: if os.path.exists(pidfile): os.remove(pidfile) else: diff --git a/run_tests.py b/run_tests.py index 7b5e2192..5c8436ae 100644 --- a/run_tests.py +++ b/run_tests.py @@ -60,7 +60,8 @@ class NovaTestRunner(core.TextTestRunner): if __name__ == '__main__': c = config.Config(stream=sys.stdout, env=os.environ, - verbosity=3) + verbosity=3, + plugins=core.DefaultPluginManager()) runner = NovaTestRunner(stream=c.stream, verbosity=c.verbosity,