summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xbin/nova-manage55
-rw-r--r--nova/api/ec2/cloud.py2
-rw-r--r--nova/auth/dbdriver.py4
-rw-r--r--nova/auth/ldapdriver.py43
-rw-r--r--nova/console/manager.py2
-rw-r--r--nova/console/xvp.py14
-rw-r--r--nova/network/manager.py2
-rw-r--r--nova/objectstore/handler.py6
-rw-r--r--nova/objectstore/image.py13
-rw-r--r--nova/rpc.py2
-rw-r--r--nova/scheduler/simple.py4
-rw-r--r--nova/twistd.py4
-rw-r--r--nova/virt/libvirt_conn.py3
-rw-r--r--nova/volume/driver.py33
-rw-r--r--nova/volume/manager.py37
-rw-r--r--nova/wsgi.py2
-rwxr-xr-xplugins/xenserver/xenapi/etc/xapi.d/plugins/pluginlib_nova.py60
-rw-r--r--run_tests.py3
18 files changed, 205 insertions, 84 deletions
diff --git a/bin/nova-manage b/bin/nova-manage
index d0901ddfc..a347e86ce 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."""
@@ -535,6 +547,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),
@@ -545,7 +597,8 @@ CATEGORIES = [
('network', NetworkCommands),
('service', ServiceCommands),
('log', LogCommands),
- ('db', DbCommands)]
+ ('db', DbCommands),
+ ('volume', VolumeCommands)]
def lazy_match(name, key_value_tuples):
diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py
index a64c9fed8..f63ec9085 100644
--- a/nova/api/ec2/cloud.py
+++ b/nova/api/ec2/cloud.py
@@ -59,7 +59,7 @@ def _gen_key(context, user_id, key_name):
# creation before creating key_pair
try:
db.key_pair_get(context, user_id, key_name)
- raise exception.Duplicate("The key_pair %s already exists"
+ raise exception.Duplicate(_("The key_pair %s already exists")
% key_name)
except exception.NotFound:
pass
diff --git a/nova/auth/dbdriver.py b/nova/auth/dbdriver.py
index 0eb6fe588..d8dad8edd 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 bc53e0ec6..a6915ce03 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/console/manager.py b/nova/console/manager.py
index c55ca8e8f..5697e7cb1 100644
--- a/nova/console/manager.py
+++ b/nova/console/manager.py
@@ -67,7 +67,7 @@ class ConsoleProxyManager(manager.Manager):
pool['id'],
instance_id)
except exception.NotFound:
- logging.debug("Adding console")
+ logging.debug(_("Adding console"))
if not password:
password = self.driver.generate_password()
if not port:
diff --git a/nova/console/xvp.py b/nova/console/xvp.py
index 2a76223da..ee66dac46 100644
--- a/nova/console/xvp.py
+++ b/nova/console/xvp.py
@@ -96,7 +96,7 @@ class XVPConsoleProxy(object):
return os.urandom(length * 2).encode('base64')[:length]
def _rebuild_xvp_conf(self, context):
- logging.debug("Rebuilding xvp conf")
+ logging.debug(_("Rebuilding xvp conf"))
pools = [pool for pool in
db.console_pool_get_all_by_host_type(context, self.host,
self.console_type)
@@ -113,12 +113,12 @@ class XVPConsoleProxy(object):
self._xvp_restart()
def _write_conf(self, config):
- logging.debug('Re-wrote %s' % FLAGS.console_xvp_conf)
+ logging.debug(_('Re-wrote %s') % FLAGS.console_xvp_conf)
with open(FLAGS.console_xvp_conf, 'w') as cfile:
cfile.write(config)
def _xvp_stop(self):
- logging.debug("Stopping xvp")
+ logging.debug(_("Stopping xvp"))
pid = self._xvp_pid()
if not pid:
return
@@ -131,19 +131,19 @@ class XVPConsoleProxy(object):
def _xvp_start(self):
if self._xvp_check_running():
return
- logging.debug("Starting xvp")
+ logging.debug(_("Starting xvp"))
try:
utils.execute('xvp -p %s -c %s -l %s' %
(FLAGS.console_xvp_pid,
FLAGS.console_xvp_conf,
FLAGS.console_xvp_log))
except exception.ProcessExecutionError, err:
- logging.error("Error starting xvp: %s" % err)
+ logging.error(_("Error starting xvp: %s") % err)
def _xvp_restart(self):
- logging.debug("Restarting xvp")
+ logging.debug(_("Restarting xvp"))
if not self._xvp_check_running():
- logging.debug("xvp not running...")
+ logging.debug(_("xvp not running..."))
self._xvp_start()
else:
pid = self._xvp_pid()
diff --git a/nova/network/manager.py b/nova/network/manager.py
index 61de8055a..5d7589090 100644
--- a/nova/network/manager.py
+++ b/nova/network/manager.py
@@ -211,7 +211,7 @@ class NetworkManager(manager.Manager):
def release_fixed_ip(self, context, mac, address):
"""Called by dhcp-bridge when ip is released."""
- LOG.debug("Releasing IP %s", address, context=context)
+ LOG.debug(_("Releasing IP %s"), address, context=context)
fixed_ip_ref = self.db.fixed_ip_get_by_address(context, address)
instance_ref = fixed_ip_ref['instance']
if not instance_ref:
diff --git a/nova/objectstore/handler.py b/nova/objectstore/handler.py
index bc26fd3c5..43ed7ffe7 100644
--- a/nova/objectstore/handler.py
+++ b/nova/objectstore/handler.py
@@ -315,8 +315,10 @@ class ObjectResource(ErrorHandlingResource):
context=request.context)
if not self.bucket.is_authorized(request.context):
- LOG.audit("Unauthorized attempt to delete object %s from "
- "bucket %s", self.name, self.bucket.name,
+ LOG.audit(_("Unauthorized attempt to delete object "
+ "%(object)s from bucket %(bucket)s") %
+ {'object': self.name,
+ 'bucket': self.bucket.name},
context=request.context)
raise exception.NotAuthorized()
diff --git a/nova/objectstore/image.py b/nova/objectstore/image.py
index abc28182e..41e0abd80 100644
--- a/nova/objectstore/image.py
+++ b/nova/objectstore/image.py
@@ -259,22 +259,25 @@ class Image(object):
process_input=encrypted_key,
check_exit_code=False)
if err:
- raise exception.Error("Failed to decrypt private key: %s" % err)
+ raise exception.Error(_("Failed to decrypt private key: %s")
+ % err)
iv, err = utils.execute(
'openssl rsautl -decrypt -inkey %s' % cloud_private_key,
process_input=encrypted_iv,
check_exit_code=False)
if err:
- raise exception.Error("Failed to decrypt initialization "
- "vector: %s" % err)
+ raise exception.Error(_("Failed to decrypt initialization "
+ "vector: %s") % err)
_out, err = utils.execute(
'openssl enc -d -aes-128-cbc -in %s -K %s -iv %s -out %s'
% (encrypted_filename, key, iv, decrypted_filename),
check_exit_code=False)
if err:
- raise exception.Error("Failed to decrypt image file %s : %s" %
- (encrypted_filename, err))
+ raise exception.Error(_("Failed to decrypt image file "
+ "%(image_file)s: %(err)s") %
+ {'image_file': encrypted_filename,
+ 'err': err})
@staticmethod
def untarzip_image(path, filename):
diff --git a/nova/rpc.py b/nova/rpc.py
index 49b11602b..bbfa71138 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 47baf0d73..baf4966d4 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 556271999..6390a8144 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/nova/virt/libvirt_conn.py b/nova/virt/libvirt_conn.py
index e70abb4e5..7005ae814 100644
--- a/nova/virt/libvirt_conn.py
+++ b/nova/virt/libvirt_conn.py
@@ -732,7 +732,8 @@ class LibvirtConnection(object):
'cpu_time': cpu_time}
def get_diagnostics(self, instance_name):
- raise exception.APIError("diagnostics are not supported for libvirt")
+ raise exception.APIError(_("diagnostics are not supported "
+ "for libvirt"))
def get_disks(self, instance_name):
"""
diff --git a/nova/volume/driver.py b/nova/volume/driver.py
index 5fefa10cf..da7307733 100644
--- a/nova/volume/driver.py
+++ b/nova/volume/driver.py
@@ -100,6 +100,14 @@ class VolumeDriver(object):
def delete_volume(self, volume):
"""Deletes a logical volume."""
+ try:
+ self._try_execute("sudo lvdisplay %s/%s" %
+ (FLAGS.volume_group,
+ volume['name']))
+ except Exception as e:
+ # If the volume isn't present, then don't attempt to delete
+ return True
+
self._try_execute("sudo lvremove -f %s/%s" %
(FLAGS.volume_group,
volume['name']))
@@ -218,8 +226,14 @@ class ISCSIDriver(VolumeDriver):
def ensure_export(self, context, volume):
"""Synchronously recreates an export for a logical volume."""
- iscsi_target = self.db.volume_get_iscsi_target_num(context,
+ try:
+ iscsi_target = self.db.volume_get_iscsi_target_num(context,
volume['id'])
+ except exception.NotFound:
+ LOG.info(_("Skipping ensure_export. No iscsi_target " +
+ "provisioned for volume: %d"), volume['id'])
+ return
+
iscsi_name = "%s%s" % (FLAGS.iscsi_target_prefix, volume['name'])
volume_path = "/dev/%s/%s" % (FLAGS.volume_group, volume['name'])
self._sync_exec("sudo ietadm --op new "
@@ -258,8 +272,23 @@ class ISCSIDriver(VolumeDriver):
def remove_export(self, context, volume):
"""Removes an export for a logical volume."""
- iscsi_target = self.db.volume_get_iscsi_target_num(context,
+ try:
+ iscsi_target = self.db.volume_get_iscsi_target_num(context,
volume['id'])
+ except exception.NotFound:
+ LOG.info(_("Skipping remove_export. No iscsi_target " +
+ "provisioned for volume: %d"), volume['id'])
+ return
+
+ try:
+ # ietadm show will exit with an error
+ # this export has already been removed
+ self._execute("sudo ietadm --op show --tid=%s " % iscsi_target)
+ except Exception as e:
+ LOG.info(_("Skipping remove_export. No iscsi_target " +
+ "is presently exported for volume: %d"), volume['id'])
+ return
+
self._execute("sudo ietadm --op delete --tid=%s "
"--lun=0" % iscsi_target)
self._execute("sudo ietadm --op delete --tid=%s" %
diff --git a/nova/volume/manager.py b/nova/volume/manager.py
index 6348539c5..82e3521a8 100644
--- a/nova/volume/manager.py
+++ b/nova/volume/manager.py
@@ -84,7 +84,10 @@ class VolumeManager(manager.Manager):
volumes = self.db.volume_get_all_by_host(ctxt, self.host)
LOG.debug(_("Re-exporting %s volumes"), len(volumes))
for volume in volumes:
- self.driver.ensure_export(ctxt, volume)
+ if volume['status'] in ['available', 'in-use']:
+ self.driver.ensure_export(ctxt, volume)
+ else:
+ LOG.info(_("volume %s: skipping export"), volume_ref['name'])
def create_volume(self, context, volume_id):
"""Creates and exports the volume."""
@@ -99,12 +102,18 @@ class VolumeManager(manager.Manager):
# before passing it to the driver.
volume_ref['host'] = self.host
- LOG.debug(_("volume %s: creating lv of size %sG"), volume_ref['name'],
- volume_ref['size'])
- self.driver.create_volume(volume_ref)
+ try:
+ LOG.debug(_("volume %s: creating lv of size %sG"),
+ volume_ref['name'],
+ volume_ref['size'])
+ self.driver.create_volume(volume_ref)
- LOG.debug(_("volume %s: creating export"), volume_ref['name'])
- self.driver.create_export(context, volume_ref)
+ LOG.debug(_("volume %s: creating export"), volume_ref['name'])
+ self.driver.create_export(context, volume_ref)
+ except Exception as e:
+ self.db.volume_update(context,
+ volume_ref['id'], {'status': 'error'})
+ raise e
now = datetime.datetime.utcnow()
self.db.volume_update(context,
@@ -121,10 +130,18 @@ class VolumeManager(manager.Manager):
raise exception.Error(_("Volume is still attached"))
if volume_ref['host'] != self.host:
raise exception.Error(_("Volume is not local to this node"))
- LOG.debug(_("volume %s: removing export"), volume_ref['name'])
- self.driver.remove_export(context, volume_ref)
- LOG.debug(_("volume %s: deleting"), volume_ref['name'])
- self.driver.delete_volume(volume_ref)
+
+ try:
+ LOG.debug(_("volume %s: removing export"), volume_ref['name'])
+ self.driver.remove_export(context, volume_ref)
+ LOG.debug(_("volume %s: deleting"), volume_ref['name'])
+ self.driver.delete_volume(volume_ref)
+ except Exception as e:
+ self.db.volume_update(context,
+ volume_ref['id'],
+ {'status': 'error_deleting'})
+ raise e
+
self.db.volume_destroy(context, volume_id)
LOG.debug(_("volume %s: deleted successfully"), volume_ref['name'])
return True
diff --git a/nova/wsgi.py b/nova/wsgi.py
index 4f5307d80..a48bede9c 100644
--- a/nova/wsgi.py
+++ b/nova/wsgi.py
@@ -143,7 +143,7 @@ class Application(object):
See the end of http://pythonpaste.org/webob/modules/dec.html
for more info.
"""
- raise NotImplementedError("You must implement __call__")
+ raise NotImplementedError(_("You must implement __call__"))
class Middleware(Application):
diff --git a/plugins/xenserver/xenapi/etc/xapi.d/plugins/pluginlib_nova.py b/plugins/xenserver/xenapi/etc/xapi.d/plugins/pluginlib_nova.py
index 8e7a829d5..cc0a196af 100755
--- a/plugins/xenserver/xenapi/etc/xapi.d/plugins/pluginlib_nova.py
+++ b/plugins/xenserver/xenapi/etc/xapi.d/plugins/pluginlib_nova.py
@@ -60,7 +60,7 @@ def ignore_failure(func, *args, **kwargs):
try:
return func(*args, **kwargs)
except XenAPI.Failure, e:
- logging.error('Ignoring XenAPI.Failure %s', e)
+ logging.error(_('Ignoring XenAPI.Failure %s'), e)
return None
@@ -78,19 +78,25 @@ def validate_exists(args, key, default=None):
"""
if key in args:
if len(args[key]) == 0:
- raise ArgumentError('Argument %r value %r is too short.' %
- (key, args[key]))
+ raise ArgumentError(_('Argument %(key)s value %(value)s is too '
+ 'short.') %
+ {'key': key,
+ 'value': args[key]})
if not ARGUMENT_PATTERN.match(args[key]):
- raise ArgumentError('Argument %r value %r contains invalid '
- 'characters.' % (key, args[key]))
+ raise ArgumentError(_('Argument %(key)s value %(value)s contains '
+ 'invalid characters.') %
+ {'key': key,
+ 'value': args[key]})
if args[key][0] == '-':
- raise ArgumentError('Argument %r value %r starts with a hyphen.'
- % (key, args[key]))
+ raise ArgumentError(_('Argument %(key)s value %(value)s starts '
+ 'with a hyphen.') %
+ {'key': key,
+ 'value': args[key]})
return args[key]
elif default is not None:
return default
else:
- raise ArgumentError('Argument %s is required.' % key)
+ raise ArgumentError(_('Argument %s is required.') % key)
def validate_bool(args, key, default=None):
@@ -105,8 +111,10 @@ def validate_bool(args, key, default=None):
elif value.lower() == 'false':
return False
else:
- raise ArgumentError("Argument %s may not take value %r. "
- "Valid values are ['true', 'false']." % (key, value))
+ raise ArgumentError(_("Argument %(key)s may not take value %(value)s. "
+ "Valid values are ['true', 'false'].")
+ % {'key': key,
+ 'value': value})
def exists(args, key):
@@ -116,7 +124,7 @@ def exists(args, key):
if key in args:
return args[key]
else:
- raise ArgumentError('Argument %s is required.' % key)
+ raise ArgumentError(_('Argument %s is required.') % key)
def optional(args, key):
@@ -149,8 +157,13 @@ def create_vdi(session, sr_ref, name_label, virtual_size, read_only):
'other_config': {},
'sm_config': {},
'tags': []})
- logging.debug('Created VDI %s (%s, %s, %s) on %s.', vdi_ref, name_label,
- virtual_size, read_only, sr_ref)
+ logging.debug(_('Created VDI %(vdi_ref)s (%(label)s, %(size)s, '
+ '%(read_only)s) on %(sr_ref)s.') %
+ {'vdi_ref': vdi_ref,
+ 'label': name_label,
+ 'size': virtual_size,
+ 'read_only': read_only,
+ 'sr_ref': sr_ref})
return vdi_ref
@@ -169,19 +182,19 @@ def with_vdi_in_dom0(session, vdi, read_only, f):
vbd_rec['qos_algorithm_type'] = ''
vbd_rec['qos_algorithm_params'] = {}
vbd_rec['qos_supported_algorithms'] = []
- logging.debug('Creating VBD for VDI %s ... ', vdi)
+ logging.debug(_('Creating VBD for VDI %s ... '), vdi)
vbd = session.xenapi.VBD.create(vbd_rec)
- logging.debug('Creating VBD for VDI %s done.', vdi)
+ logging.debug(_('Creating VBD for VDI %s done.'), vdi)
try:
- logging.debug('Plugging VBD %s ... ', vbd)
+ logging.debug(_('Plugging VBD %s ... '), vbd)
session.xenapi.VBD.plug(vbd)
- logging.debug('Plugging VBD %s done.', vbd)
+ logging.debug(_('Plugging VBD %s done.'), vbd)
return f(session.xenapi.VBD.get_device(vbd))
finally:
- logging.debug('Destroying VBD for VDI %s ... ', vdi)
+ logging.debug(_('Destroying VBD for VDI %s ... '), vdi)
vbd_unplug_with_retry(session, vbd)
ignore_failure(session.xenapi.VBD.destroy, vbd)
- logging.debug('Destroying VBD for VDI %s done.', vdi)
+ logging.debug(_('Destroying VBD for VDI %s done.'), vdi)
def vbd_unplug_with_retry(session, vbd):
@@ -192,19 +205,20 @@ def vbd_unplug_with_retry(session, vbd):
while True:
try:
session.xenapi.VBD.unplug(vbd)
- logging.debug('VBD.unplug successful first time.')
+ logging.debug(_('VBD.unplug successful first time.'))
return
except XenAPI.Failure, e:
if (len(e.details) > 0 and
e.details[0] == 'DEVICE_DETACH_REJECTED'):
- logging.debug('VBD.unplug rejected: retrying...')
+ logging.debug(_('VBD.unplug rejected: retrying...'))
time.sleep(1)
elif (len(e.details) > 0 and
e.details[0] == 'DEVICE_ALREADY_DETACHED'):
- logging.debug('VBD.unplug successful eventually.')
+ logging.debug(_('VBD.unplug successful eventually.'))
return
else:
- logging.error('Ignoring XenAPI.Failure in VBD.unplug: %s', e)
+ logging.error(_('Ignoring XenAPI.Failure in VBD.unplug: %s'),
+ e)
return
diff --git a/run_tests.py b/run_tests.py
index 7b5e2192a..5c8436aee 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,