diff --git a/cinder/tests/unit/volume/drivers/ibm/test_ds8k_proxy.py b/cinder/tests/unit/volume/drivers/ibm/test_ds8k_proxy.py index 35ddcece93c..2c1fd141fcb 100644 --- a/cinder/tests/unit/volume/drivers/ibm/test_ds8k_proxy.py +++ b/cinder/tests/unit/volume/drivers/ibm/test_ds8k_proxy.py @@ -4513,3 +4513,89 @@ class DS8KProxyTest(test.TestCase): lun = ds8kproxy.Lun(volume) exp_repl_name = helper.filter_alnum(volume.name)[:16] self.assertEqual(lun.replica_ds_name, exp_repl_name) + + @mock.patch.object(eventlet, 'sleep') + @mock.patch.object(helper.DS8KCommonHelper, 'get_flashcopy') + def test_revert_to_snapshot_normal_vol(self, mock_get_flashcopy, + mock_sleep): + self.driver = FakeDS8KProxy(self.storage_info, self.logger, + self.exception, self) + self.driver.setup(self.ctxt) + + vol_type = testutils.create_volume_type(self.ctxt, name='VOL_TYPE') + location = six.text_type({'vol_hex_id': '0002'}) + volume = self._create_volume(volume_type_id=vol_type.id, + provider_location=location) + snapshot = self._create_snapshot(volume_id=volume.id) + + mock_get_flashcopy.side_effect = [[TEST_FLASHCOPY], {}] + + self.driver.revert_to_snapshot(self.ctxt, volume, snapshot) + + @mock.patch.object(eventlet, 'sleep') + @mock.patch.object(helper.DS8KCommonHelper, 'get_flashcopy') + def test_revert_to_snapshot_replication_vol(self, mock_get_flashcopy, + mock_sleep): + """test a successful creation of snapshot.""" + self.configuration.replication_device = [TEST_REPLICATION_DEVICE] + self.driver = FakeDS8KProxy(self.storage_info, self.logger, + self.exception, self) + self.driver.setup(self.ctxt) + + extra_specs = {'replication_enabled': ' True'} + vol_type = testutils.create_volume_type(self.ctxt, name='VOL_TYPE', + extra_specs=extra_specs) + location = six.text_type({'vol_hex_id': '0002'}) + volume = self._create_volume(volume_type_id=vol_type.id, + provider_location=location) + snapshot = self._create_snapshot(volume_id=volume.id) + + mock_get_flashcopy.side_effect = [[TEST_FLASHCOPY], {}] + + self.assertRaises(exception.VolumeDriverException, + self.driver.revert_to_snapshot, + self.ctxt, volume, snapshot) + + @mock.patch.object(eventlet, 'sleep') + @mock.patch.object(helper.DS8KCommonHelper, 'get_flashcopy') + def test_revert_to_snapshot_tar_vol_is_in_fc(self, mock_get_flashcopy, + mock_sleep): + self.driver = FakeDS8KProxy(self.storage_info, self.logger, + self.exception, self) + self.driver.setup(self.ctxt) + + vol_type = testutils.create_volume_type(self.ctxt, name='VOL_TYPE') + location = six.text_type({'vol_hex_id': 'fake_volume_id_2'}) + volume = self._create_volume(volume_type_id=vol_type.id, + provider_location=location) + snapshot = self._create_snapshot(volume_id=volume.id) + + mock_get_flashcopy.side_effect = [[TEST_FLASHCOPY], {}] + + self.assertRaises(exception.VolumeBackendAPIException, + self.driver.revert_to_snapshot, + self.ctxt, volume, snapshot) + + @mock.patch.object(eventlet, 'sleep') + @mock.patch.object(helper.DS8KCommonHelper, 'get_flashcopy') + def test_revert_to_snapshot_with_diff_size(self, mock_get_flashcopy, + mock_sleep): + self.driver = FakeDS8KProxy(self.storage_info, self.logger, + self.exception, self) + self.driver.setup(self.ctxt) + + vol_type = testutils.create_volume_type(self.ctxt, name='VOL_TYPE') + location = six.text_type({'vol_hex_id': 'fake_volume_id_2'}) + volume = self._create_volume(volume_type_id=vol_type.id, + provider_location=location) + snapshot = self._create_snapshot(volume_id=volume.id) + + volume1 = self._create_volume(volume_type_id=vol_type.id, + provider_location=location, + size=2) + + mock_get_flashcopy.side_effect = [[TEST_FLASHCOPY], {}] + + self.assertRaises(exception.InvalidInput, + self.driver.revert_to_snapshot, + self.ctxt, volume1, snapshot) diff --git a/cinder/volume/drivers/ibm/ibm_storage/ds8k_proxy.py b/cinder/volume/drivers/ibm/ibm_storage/ds8k_proxy.py index 6f97bf7e43b..fa207bd7b16 100644 --- a/cinder/volume/drivers/ibm/ibm_storage/ds8k_proxy.py +++ b/cinder/volume/drivers/ibm/ibm_storage/ds8k_proxy.py @@ -143,9 +143,10 @@ class Lun(object): 2.1.1 - Added support for replication consistency group. 2.1.2 - Added support for cloning volume asynchronously. 2.3.0 - Added support for reporting backend state. + 2.5.0 - Added support for revert to snapshot operation. """ - VERSION = "2.3.0" + VERSION = "2.5.0" class FakeLun(object): @@ -1059,6 +1060,31 @@ class DS8KProxy(proxy.IBMStorageProxy): volume_update = lun.get_volume_update() return True, volume_update + @proxy._trace_time + @proxy.logger + def revert_to_snapshot(self, context, volume, snapshot): + """Revert volume to snapshot.""" + if snapshot.volume_size != volume.size: + raise exception.InvalidInput( + reason=_('Reverting volume is not supported if the volume ' + 'size is not equal to the snapshot size.')) + + vol_lun = Lun(volume) + snap_lun = Lun(snapshot, is_snapshot=True) + if vol_lun.type_replication: + raise exception.VolumeDriverException( + message=_('Driver does not support revert to snapshot ' + 'of replicated volume.')) + + try: + self._clone_lun(snap_lun, vol_lun) + except Exception as err: + msg = (_("Reverting volume %(vol)s to snapshot %(snap)s failed " + "due to: %(err)s.") + % {"vol": volume.name, "snap": snapshot.name, "err": err}) + LOG.error(msg) + raise exception.VolumeBackendAPIException(data=msg) + @proxy._trace_time @proxy.logger def initialize_connection(self, volume, connector, **kwargs): diff --git a/cinder/volume/drivers/ibm/ibm_storage/ibm_storage.py b/cinder/volume/drivers/ibm/ibm_storage/ibm_storage.py index 8b28cac0ff7..d8685ec01aa 100644 --- a/cinder/volume/drivers/ibm/ibm_storage/ibm_storage.py +++ b/cinder/volume/drivers/ibm/ibm_storage/ibm_storage.py @@ -241,6 +241,10 @@ class IBMStorageDriver(san.SanDriver, return self.proxy.retype(ctxt, volume, new_type, diff, host) + def revert_to_snapshot(self, ctxt, volume, snapshot): + """Revert volume to snapshot.""" + return self.proxy.revert_to_snapshot(ctxt, volume, snapshot) + def create_group(self, context, group): """Creates a group.""" diff --git a/cinder/volume/drivers/ibm/ibm_storage/proxy.py b/cinder/volume/drivers/ibm/ibm_storage/proxy.py index 9d9f98f28dd..4e0e7cf442c 100644 --- a/cinder/volume/drivers/ibm/ibm_storage/proxy.py +++ b/cinder/volume/drivers/ibm/ibm_storage/proxy.py @@ -216,6 +216,11 @@ class IBMStorageProxy(object): """Convert the volume to be of the new type.""" pass + @_trace_time + def revert_to_snapshot(self, context, volume, snapshot): + """Revert volume to snapshot.""" + pass + @_trace_time def _get_bunch_from_host( self, connector, host_id=0, host_name=None, chap=None): diff --git a/doc/source/reference/support-matrix.ini b/doc/source/reference/support-matrix.ini index 123f4d067b0..5e08df5fed1 100644 --- a/doc/source/reference/support-matrix.ini +++ b/doc/source/reference/support-matrix.ini @@ -852,7 +852,7 @@ driver.huawei_18000=missing driver.huawei_dorado=missing driver.huawei_fusionstorage=missing driver.infinidat=missing -driver.ibm_ds8k=missing +driver.ibm_ds8k=complete driver.ibm_flashsystem=missing driver.ibm_gpfs=missing driver.ibm_storwize=complete diff --git a/releasenotes/notes/Ds8k-revert-to-snapshot-support-ea0e06e14a8710ee.yaml b/releasenotes/notes/Ds8k-revert-to-snapshot-support-ea0e06e14a8710ee.yaml new file mode 100644 index 00000000000..1a7c5ec24bc --- /dev/null +++ b/releasenotes/notes/Ds8k-revert-to-snapshot-support-ea0e06e14a8710ee.yaml @@ -0,0 +1,4 @@ +--- +features: + - | + IBM DS8000 Driver: Add support for revert-to-snapshot operation.