From d386210bc776a599bb31553c96e2a8a43acac61d Mon Sep 17 00:00:00 2001 From: Florian Haas Date: Mon, 20 Jan 2014 22:42:11 +0100 Subject: [PATCH] VolumeManager: initialize even if a volume can't be found If a previously volume cannot be exported (for example, because an iSCSI target's backing LV is no longer present), VolumeManager would previously bail out, leaving the volume service uninitialized. This left volumes dangling in limbo: their state would be reported as available (clearly not a reflection of reality), and they could not be deleted (because the volume service that would be responsible for deletion was unavailable). Instead, catch an exception raised by ensure_export() separately, log it, and set the volume to the error state. For the tgt backend, this will also remove the volume_path file. Previously this would cause an ISCSITargetRemoveFailed exception when the volume would be removed. Instead, simply log a warning and return, the way other backends (example: RBD) already do. Also, add an info message that reflects the actual path and contents of the volume_path file. Finally, fix up the tgtadm unit test so that it tests for identical IQNs, Closes-bug: 1270959. Change-Id: Id61407c9a5e020d5a823dd7b8c973d237c35cb9b --- cinder/brick/iscsi/iscsi.py | 8 ++++++++ cinder/volume/manager.py | 10 +++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/cinder/brick/iscsi/iscsi.py b/cinder/brick/iscsi/iscsi.py index ceac1b9c2..fa627b0c9 100644 --- a/cinder/brick/iscsi/iscsi.py +++ b/cinder/brick/iscsi/iscsi.py @@ -177,6 +177,9 @@ class TgtAdm(TargetAdmin): f = open(volume_path, 'w+') f.write(volume_conf) f.close() + LOG.debug(_('Created volume path %(vp)s,\n' + 'content: %(vc)%') + % {'vp': volume_path, 'vc': volume_conf}) old_persist_file = None old_name = kwargs.get('old_name', None) @@ -263,6 +266,11 @@ class TgtAdm(TargetAdmin): LOG.info(_('Removing iscsi_target for: %s') % vol_id) vol_uuid_file = vol_name volume_path = os.path.join(self.volumes_dir, vol_uuid_file) + if not os.path.exists(volume_path): + LOG.warning(_('Volume path %s does not exist, ' + 'nothing to remove.') % volume_path) + return + if os.path.isfile(volume_path): iqn = '%s%s' % (self.iscsi_target_prefix, vol_uuid_file) diff --git a/cinder/volume/manager.py b/cinder/volume/manager.py index 116b65872..95bc0c307 100644 --- a/cinder/volume/manager.py +++ b/cinder/volume/manager.py @@ -251,7 +251,15 @@ class VolumeManager(manager.SchedulerDependentManager): # calculate allocated capacity for driver sum += volume['size'] self.stats['allocated_capacity_gb'] = sum - self.driver.ensure_export(ctxt, volume) + try: + self.driver.ensure_export(ctxt, volume) + except Exception as export_ex: + LOG.error(_("Failed to re-export volume %s: " + "setting to error state"), volume['id']) + LOG.exception(export_ex) + self.db.volume_update(ctxt, + volume['id'], + {'status': 'error'}) elif volume['status'] == 'downloading': LOG.info(_("volume %s stuck in a downloading state"), volume['id']) -- 2.45.2