--- a/components/openstack/nova/files/solariszones/driver.py Tue Dec 15 00:08:40 2015 -0800
+++ b/components/openstack/nova/files/solariszones/driver.py Tue Dec 15 00:08:40 2015 -0800
@@ -170,6 +170,28 @@
except Exception:
raise
+def zonemgr_strerror(ex):
+ """Format the payload from a zonemgr(3RAD) rad.client.ObjectError
+ exception into a sensible error string that can be logged. Newlines
+ are converted to a colon-space string to create a single line.
+
+ If the exception was something other than rad.client.ObjectError,
+ just return it as a string.
+ """
+ if not isinstance(ex, rad.client.ObjectError):
+ return str(ex)
+ payload = ex.get_payload()
+ if payload.code == zonemgr.ErrorCode.NONE:
+ return str(ex)
+ error = [str(payload.code)]
+ if payload.str is not None and payload.str != '':
+ error.append(payload.str)
+ if payload.stderr is not None and payload.stderr != '':
+ stderr = payload.stderr.rstrip()
+ error.append(stderr.replace('\n', ': '))
+ result = ': '.join(error)
+ return result
+
class ZoneConfig(object):
"""ZoneConfig - context manager for access zone configurations.
@@ -189,9 +211,10 @@
self.zone.editConfig()
self.editing = True
return self
- except rad.client.ObjectError as err:
+ except Exception as ex:
+ reason = zonemgr_strerror(ex)
LOG.error(_("Unable to initialize editing of instance '%s' via "
- "zonemgr(3RAD): %s") % (self.zone.name, err))
+ "zonemgr(3RAD): %s") % (self.zone.name, reason))
raise
def __exit__(self, exc_type, exc_val, exc_tb):
@@ -207,10 +230,11 @@
# commit the config
try:
self.zone.commitConfig()
- except rad.client.ObjectError as err:
+ except Exception as ex:
+ reason = zonemgr_strerror(ex)
LOG.error(_("Unable to commit the new configuration for "
"instance '%s' via zonemgr(3RAD): %s")
- % (self.zone.name, err))
+ % (self.zone.name, reason))
# Last ditch effort to cleanup.
self.zone.cancelConfig()
@@ -233,10 +257,11 @@
self.zone.setResourceProperties(
zonemgr.Resource(resource),
[zonemgr.Property(prop, value)])
- except rad.client.ObjectError as err:
+ except Exception as ex:
+ reason = zonemgr_strerror(ex)
LOG.error(_("Unable to set '%s' property on '%s' resource for "
"instance '%s' via zonemgr(3RAD): %s")
- % (prop, resource, self.zone.name, err))
+ % (prop, resource, self.zone.name, reason))
raise
def addresource(self, resource, props=None):
@@ -246,10 +271,18 @@
try:
self.zone.addResource(zonemgr.Resource(resource, props))
- except rad.client.ObjectError as err:
+ except Exception as ex:
+ if isinstance(ex, rad.client.ObjectError):
+ code = ex.get_payload().code
+ if (ignore_exists and
+ code == zonemgr.ErrorCode.RESOURCE_ALREADY_EXISTS):
+ self.zone.setResourceProperties(zonemgr.Resource(
+ resource, None), props)
+ return
+ reason = zonemgr_strerror(ex)
LOG.error(_("Unable to create new resource '%s' for instance '%s'"
"via zonemgr(3RAD): %s")
- % (resource, self.zone.name, err))
+ % (resource, self.zone.name, reason))
raise
def removeresources(self, resource, props=None):
@@ -261,9 +294,11 @@
try:
self.zone.removeResources(zonemgr.Resource(resource, props))
- except rad.client.ObjectError as err:
+ except Exception as ex:
+ reason = zonemgr_strerror(ex)
LOG.error(_("Unable to remove resource '%s' for instance '%s' via "
- "zonemgr(3RAD): %s") % (resource, self.zone.name, err))
+ "zonemgr(3RAD): %s")
+ % (resource, self.zone.name, reason))
raise
@@ -369,7 +404,7 @@
out = None
try:
out, err = utils.execute('/usr/sbin/fcinfo', 'hba-port')
- except processutils.ProcessExecutionError as err:
+ except processutils.ProcessExecutionError:
return []
if out is None:
@@ -578,8 +613,6 @@
name = instance['name']
zone = self._get_zone_by_name(name)
if zone is None:
- LOG.error(_("Unable to find instance '%s' via zonemgr(3RAD)")
- % name)
raise exception.InstanceNotFound(instance_id=name)
return {
'state': self._get_state(zone),
@@ -835,9 +868,10 @@
out, err = utils.execute('/usr/sbin/suriadm', 'lookup-uri',
'-p', 'target=naa.%s' % target_wwn,
'-p', 'lun=%s' % target_lun)
- except processutils.ProcessExecutionError as err:
+ except processutils.ProcessExecutionError as ex:
+ reason = ex.stderr
LOG.error(_("Lookup failure of Fibre Channel volume '%s', lun "
- "%s: %s") % (target_wwn, target_lun, err.stderr))
+ "%s: %s") % (target_wwn, target_lun, reason))
raise
lines = out.split('\n')
@@ -1186,7 +1220,8 @@
self._set_memory_cap(name, instance['memory_mb'], brand)
self._set_network(context, name, instance, network_info, brand,
sc_dir)
- except Exception as reason:
+ except Exception as ex:
+ reason = zonemgr_strerror(ex)
LOG.error(_("Unable to create configuration for instance '%s' via "
"zonemgr(3RAD): %s") % (name, reason))
raise
@@ -1211,16 +1246,16 @@
try:
out, err = utils.execute('/usr/sbin/svccfg', '-s',
VNC_CONSOLE_BASE_FMRI, 'add', name)
- except processutils.ProcessExecutionError as err:
+ except processutils.ProcessExecutionError as ex:
if self._has_vnc_console_service(instance):
LOG.debug(_("Ignoring attempt to create existing zone VNC "
"console SMF service for instance '%s'") % name)
return
- else:
- LOG.error(_("Unable to create zone VNC console SMF service "
- "'{0}': {1}").format(
- VNC_CONSOLE_BASE_FMRI + ':' + name, err))
- raise
+ reason = ex.stderr
+ LOG.error(_("Unable to create zone VNC console SMF service "
+ "'{0}': {1}").format(
+ VNC_CONSOLE_BASE_FMRI + ':' + name, reason))
+ raise
def _delete_vnc_console_service(self, instance):
"""Delete a VNC console SMF service for a Solaris Zone"""
@@ -1231,17 +1266,17 @@
out, err = utils.execute('/usr/sbin/svccfg', '-s',
VNC_CONSOLE_BASE_FMRI, 'delete', '-f',
name)
- except processutils.ProcessExecutionError as err:
+ except processutils.ProcessExecutionError as ex:
if not self._has_vnc_console_service(instance):
LOG.debug(_("Ignoring attempt to delete a non-existent zone "
"VNC console SMF service for instance '%s'")
% name)
return
- else:
- LOG.error(_("Unable to delete zone VNC console SMF service "
- "'%s': %s")
- % (VNC_CONSOLE_BASE_FMRI + ':' + name, err))
- raise
+ reason = ex.stderr
+ LOG.error(_("Unable to delete zone VNC console SMF service '%s': "
+ "%s")
+ % (VNC_CONSOLE_BASE_FMRI + ':' + name, reason))
+ raise
def _enable_vnc_console_service(self, instance):
"""Enable a zone VNC console SMF service"""
@@ -1259,13 +1294,15 @@
'refresh')
out, err = utils.execute('/usr/sbin/svcadm', 'enable',
console_fmri)
- except processutils.ProcessExecutionError as err:
+ except processutils.ProcessExecutionError as ex:
if not self._has_vnc_console_service(instance):
LOG.debug(_("Ignoring attempt to enable a non-existent zone "
"VNC console SMF service for instance '%s'")
% name)
+ return
+ reason = ex.stderr
LOG.error(_("Unable to start zone VNC console SMF service "
- "'%s': %s") % (console_fmri, err))
+ "'%s': %s") % (console_fmri, reason))
raise
# Allow some time for the console service to come online.
@@ -1286,9 +1323,10 @@
# Wait for service state to transition to (hopefully) online
# state or offline/maintenance states.
greenthread.sleep(2)
- except processutils.ProcessExecutionError as err:
+ except processutils.ProcessExecutionError as ex:
+ reason = ex.stderr
LOG.error(_("Error querying state of zone VNC console SMF "
- "service '%s': %s") % (console_fmri, err))
+ "service '%s': %s") % (console_fmri, reason))
raise
# TODO(npower): investigate using RAD instead of CLI invocation
try:
@@ -1298,10 +1336,11 @@
'setprop', 'vnc/nova-enabled=false')
out, err = utils.execute('/usr/sbin/svccfg', '-s', console_fmri,
'refresh')
- except processutils.ProcessExecutionError as err:
+ except processutils.ProcessExecutionError as ex:
+ reason = ex.stderr
LOG.error(_("Unable to update 'vnc/nova-enabled' property for "
"zone VNC console SMF service "
- "'%s': %s") % (console_fmri, err))
+ "'%s': %s") % (console_fmri, reason))
raise
def _disable_vnc_console_service(self, instance):
@@ -1316,18 +1355,20 @@
try:
out, err = utils.execute('/usr/sbin/svcadm', 'disable',
console_fmri)
- except processutils.ProcessExecutionError as err:
+ except processutils.ProcessExecutionError as ex:
+ reason = ex.stderr
LOG.error(_("Unable to disable zone VNC console SMF service "
- "'%s': %s") % (console_fmri, err))
+ "'%s': %s") % (console_fmri, reason))
# The console service sets a SMF instance property for the port
# on which the VNC service is listening. The service needs to be
# refreshed to reset the property value
try:
out, err = utils.execute('/usr/sbin/svccfg', '-s', console_fmri,
'refresh')
- except processutils.ProcessExecutionError as err:
+ except processutils.ProcessExecutionError as ex:
+ reason = ex.stderr
LOG.error(_("Unable to refresh zone VNC console SMF service "
- "'%s': %s") % (console_fmri, err))
+ "'%s': %s") % (console_fmri, reason))
def _get_vnc_console_service_state(self, instance):
"""Returns state of the instance zone VNC console SMF service"""
@@ -1343,9 +1384,11 @@
state, err = utils.execute('/usr/sbin/svcs', '-H', '-o', 'state',
console_fmri)
return state.strip()
- except processutils.ProcessExecutionError as err:
+ except processutils.ProcessExecutionError as ex:
+ reason = ex.stderr
LOG.error(_("Console state request failed for zone VNC console "
- "SMF service for instance '%s': %s") % (name, err))
+ "SMF service for instance '%s': %s")
+ % (name, reason))
raise
def _has_vnc_console_service(self, instance):
@@ -1357,7 +1400,7 @@
utils.execute('/usr/bin/svcs', '-H', '-o', 'state',
console_fmri)
return True
- except processutils.ProcessExecutionError as err:
+ except Exception:
return False
def _install(self, instance, image, sc_dir):
@@ -1383,7 +1426,8 @@
LOG.debug(_("Installing instance '%s' (%s)") %
(name, instance['display_name']))
zone.install(options=options)
- except Exception as reason:
+ except Exception as ex:
+ reason = zonemgr_strerror(ex)
LOG.error(_("Unable to install root file system for instance '%s' "
"via zonemgr(3RAD): %s") % (name, reason))
raise
@@ -1400,7 +1444,8 @@
try:
zone.boot()
- except Exception as reason:
+ except Exception as ex:
+ reason = zonemgr_strerror(ex)
LOG.error(_("Unable to power on instance '%s' via zonemgr(3RAD): "
"%s") % (name, reason))
raise exception.InstancePowerOnFailure(reason=reason)
@@ -1418,7 +1463,8 @@
return
try:
zone.uninstall(['-F'])
- except Exception as reason:
+ except Exception as ex:
+ reason = zonemgr_strerror(ex)
LOG.error(_("Unable to uninstall root file system for instance "
"'%s' via zonemgr(3RAD): %s") % (name, reason))
raise
@@ -1432,7 +1478,8 @@
zonemanager = self.rad_connection.get_object(zonemgr.ZoneManager())
try:
zonemanager.delete(name)
- except Exception as reason:
+ except Exception as ex:
+ reason = zonemgr_strerror(ex)
LOG.error(_("Unable to delete configuration for instance '%s' via "
"zonemgr(3RAD): %s") % (name, reason))
raise
@@ -1479,12 +1526,12 @@
try:
connection_info = self._connect_boot_volume(volume, mountpoint,
context, instance)
- except exception.InvalidVolume as badvol:
+ except exception.InvalidVolume as reason:
# This Cinder volume is not usable for ZOSS so discard it.
# zonecfg will apply default zonepath dataset configuration
# instead. Carry on
LOG.warning(_("Volume '%s' is being discarded: %s")
- % (volume_id, badvol))
+ % (volume_id, reason))
self._volume_api.delete(context, volume_id)
connection_info = None
except Exception as reason:
@@ -1505,7 +1552,8 @@
self._install(instance, image, sc_dir)
installed = True
self._power_on(instance)
- except Exception as reason:
+ except Exception as ex:
+ reason = zonemgr_strerror(ex)
LOG.error(_("Unable to spawn instance '%s' via zonemgr(3RAD): %s")
% (name, reason))
if installed:
@@ -1545,14 +1593,15 @@
else:
# 'HARD'
zone.halt()
- except rad.client.ObjectError as reason:
- result = reason.get_payload()
- if result.code == zonemgr.ErrorCode.COMMAND_ERROR:
- LOG.warning(_("Ignoring command error returned while trying "
- "to power off instance '%s' via zonemgr(3RAD): "
- "%s" % (name, reason)))
- return
- except Exception as reason:
+ except Exception as ex:
+ reason = zonemgr_strerror(ex)
+ if isinstance(ex, rad.client.ObjectError):
+ code = ex.get_payload().code
+ if code == zonemgr.ErrorCode.COMMAND_ERROR:
+ LOG.warning(_("Ignoring command error returned while "
+ "trying to power off instance '%s' via "
+ "zonemgr(3RAD): %s" % (name, reason)))
+ return
LOG.error(_("Unable to power off instance '%s' via zonemgr(3RAD): "
"%s") % (name, reason))
raise exception.InstancePowerOffFailure(reason=reason)
@@ -1599,7 +1648,8 @@
self._uninstall(instance)
if self._get_state(zone) == power_state.NOSTATE:
self._delete_config(instance)
- except Exception as reason:
+ except Exception as ex:
+ reason = zonemgr_strerror(ex)
LOG.warning(_("Unable to destroy instance '%s' via zonemgr(3RAD): "
"%s") % (name, reason))
@@ -1653,7 +1703,8 @@
zone.shutdown(['-r'])
else:
zone.reboot()
- except Exception as reason:
+ except Exception as ex:
+ reason = zonemgr_strerror(ex)
LOG.error(_("Unable to reboot instance '%s' via zonemgr(3RAD): %s")
% (name, reason))
raise exception.InstanceRebootFailure(reason=reason)
@@ -1741,9 +1792,10 @@
try:
out, err = utils.execute('/usr/sbin/svccfg', '-s', console_fmri,
'refresh')
- except processutils.ProcessExecutionError as err:
+ except processutils.ProcessExecutionError as ex:
+ reason = ex.stderr
LOG.error(_("Unable to refresh zone VNC console SMF service "
- "'%s': %s" % (console_fmri, err)))
+ "'%s': %s" % (console_fmri, reason)))
raise
host = CONF.vncserver_proxyclient_address
@@ -1754,10 +1806,11 @@
return ctype.ConsoleVNC(host=host,
port=port,
internal_access_path=None)
- except processutils.ProcessExecutionError as err:
+ except processutils.ProcessExecutionError as ex:
+ reason = ex.stderr
LOG.error(_("Unable to read VNC console port from zone VNC "
"console SMF service '%s': %s"
- % (console_fmri, err)))
+ % (console_fmri, reason)))
def get_spice_console(self, context, instance):
"""Get connection info for a spice console.
@@ -1829,8 +1882,6 @@
name = instance['name']
zone = self._get_zone_by_name(name)
if zone is None:
- LOG.error(_("Unable to find instance '%s' via zonemgr(3RAD)")
- % name)
raise exception.InstanceNotFound(instance_id=name)
return self._get_zone_diagnostics(zone)
@@ -2030,7 +2081,7 @@
image_id,
metadata,
None)
- except exception.Invalid as invalid:
+ except exception.Invalid:
LOG.warning(_("Image service rejected image metadata "
"container and disk formats 'uar' and "
"'zfs'. Using generic values 'ovf' and "
@@ -2205,9 +2256,10 @@
try:
value = None
(out, _err) = utils.execute('/usr/sbin/zpool', 'get', prop, zpool)
- except processutils.ProcessExecutionError as err:
+ except processutils.ProcessExecutionError as ex:
+ reason = ex.stderr
LOG.error(_("Failed to get property '%s' from zpool '%s': %s")
- % (prop, zpool, err.stderr))
+ % (prop, zpool, reason))
return value
zpool_prop = out.splitlines()[1].split()
@@ -2363,9 +2415,10 @@
self._live_migration(name, dest, dry_run=False)
except Exception as ex:
with excutils.save_and_reraise_exception():
+ reason = zonemgr_strerror(ex)
LOG.error(_("Unable to live migrate instance '%s' to host "
"'%s' via zonemgr(3RAD): %s")
- % (name, dest, ex))
+ % (name, dest, reason))
recover_method(context, instance, dest, block_migration)
post_method(context, instance, dest, block_migration, migrate_data)
@@ -2418,8 +2471,9 @@
try:
self._delete_config(instance)
except Exception as ex:
+ reason = zonemgr_strerror(ex)
LOG.error(_("Unable to delete configuration for instance '%s' via "
- "zonemgr(3RAD): %s") % (name, ex))
+ "zonemgr(3RAD): %s") % (name, reason))
raise
def post_live_migration_at_source(self, context, instance, network_info):
@@ -2560,7 +2614,8 @@
try:
self._live_migration(name, dest, dry_run=True)
except Exception as ex:
- raise exception.MigrationPreCheckError(reason=ex)
+ reason = zonemgr_strerror(ex)
+ raise exception.MigrationPreCheckError(reason=reason)
return dest_check_data
def get_instance_disk_info(self, instance_name,