From 56ee0971b3a74240fdd008b090b46ec9917d1ee2 Mon Sep 17 00:00:00 2001 From: Ajitha Robert Date: Mon, 12 Oct 2020 08:31:27 -0400 Subject: [PATCH] Nimble: Add support for revert to snapshot blueprint nimble-add-revert-to-snapshot-support Change-Id: I63f4ae165486451b8c3da2e5d7a40a4c2a96ad4a --- .../tests/unit/volume/drivers/test_nimble.py | 59 +++++++++++++++++++ cinder/volume/drivers/nimble.py | 27 +++++++++ .../drivers/nimble-volume-driver.rst | 2 +- doc/source/reference/support-matrix.ini | 2 +- .../notes/1899512-7a872a2c19e53536.yaml | 4 ++ 5 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 releasenotes/notes/1899512-7a872a2c19e53536.yaml diff --git a/cinder/tests/unit/volume/drivers/test_nimble.py b/cinder/tests/unit/volume/drivers/test_nimble.py index 68a6b8cec37..d0ee0032a74 100644 --- a/cinder/tests/unit/volume/drivers/test_nimble.py +++ b/cinder/tests/unit/volume/drivers/test_nimble.py @@ -154,6 +154,13 @@ FAKE_IGROUP_LIST_RESPONSE_FC = [ {'wwpn': '10:00:00:00:00:00:00:01'}], 'name': 'test-igrp2'}] +FAKE_GET_VOL_INFO_REVERT = {'name': 'testvolume', + 'id': fake.VOLUME_ID, + 'clone': False, + 'target_name': 'iqn.test', + 'online': True, + 'agent_type': 'openstack', + 'last_snap': {'snap_id': fake.SNAPSHOT_ID}} FAKE_CREATE_VOLUME_NEGATIVE_RESPONSE = exception.VolumeBackendAPIException( "Volume testvolume not found") @@ -173,6 +180,9 @@ FAKE_CREATE_VOLUME_NEGATIVE_DEDUPE = exception.VolumeBackendAPIException( FAKE_CREATE_VOLUME_NEGATIVE_QOS = exception.VolumeBackendAPIException( "Please set valid IOPS limitin the range [256, 4294967294]") +FAKE_VOLUME_RESTORE_NEGATIVE_RESPONSE = exception.VolumeBackendAPIException( + "No recent Snapshot found") + FAKE_POSITIVE_GROUP_INFO_RESPONSE = { 'version_current': '3.0.0.0', 'group_target_enabled': False, @@ -1189,6 +1199,55 @@ class NimbleDriverSnapshotTestCase(NimbleDriverBaseTestCase): 'limit': 100}})] self.mock_client_service.assert_has_calls(expected_calls) + @mock.patch(NIMBLE_URLLIB2) + @mock.patch(NIMBLE_CLIENT) + @NimbleDriverBaseTestCase.client_mock_decorator(create_configuration( + 'nimble', 'nimble_pass', '10.18.108.55', 'default', '*')) + def test_revert_to_snapshot(self): + self.mock_client_service.online_vol.return_value = ( + FAKE_GENERIC_POSITIVE_RESPONSE) + self.mock_client_service.volume_restore.return_value = ( + FAKE_GENERIC_POSITIVE_RESPONSE) + self.mock_client_service.get_vol_info.return_value = ( + FAKE_GET_VOL_INFO_REVERT) + self.mock_client_service.get_netconfig.return_value = ( + FAKE_POSITIVE_NETCONFIG_RESPONSE) + ctx = context.get_admin_context() + self.driver.revert_to_snapshot(ctx, + {'id': fake.VOLUME_ID, + 'size': 1, + 'name': 'testvolume'}, + {'id': fake.SNAPSHOT_ID, + 'volume_id': fake.VOLUME_ID}) + expected_calls = [mock.call.online_vol('testvolume', False), + mock.call.volume_restore('testvolume', + {'data': {'id': fake.VOLUME_ID, + 'base_snap_id': fake.SNAPSHOT_ID}}), + mock.call.online_vol('testvolume', True)] + self.mock_client_service.assert_has_calls(expected_calls) + + @mock.patch(NIMBLE_URLLIB2) + @mock.patch(NIMBLE_CLIENT) + @NimbleDriverBaseTestCase.client_mock_decorator(create_configuration( + 'nimble', 'nimble_pass', '10.18.108.55', 'default', '*')) + def test_revert_to_snapshot_negative(self): + self.mock_client_service.online_vol.return_value = ( + FAKE_GENERIC_POSITIVE_RESPONSE) + self.mock_client_service.volume_restore.side_effect = ( + FAKE_VOLUME_RESTORE_NEGATIVE_RESPONSE) + self.mock_client_service.get_vol_info.return_value = ( + FAKE_GET_VOL_INFO_REVERT) + self.mock_client_service.get_netconfig.return_value = ( + FAKE_POSITIVE_NETCONFIG_RESPONSE) + ctx = context.get_admin_context() + self.assertRaises(exception.VolumeBackendAPIException, + self.driver.revert_to_snapshot, ctx, + {'id': fake.VOLUME_ID, + 'size': 1, + 'name': 'testvolume'}, + {'id': fake.SNAPSHOT_ID, + 'volume_id': fake.VOLUME_ID}) + class NimbleDriverConnectionTestCase(NimbleDriverBaseTestCase): diff --git a/cinder/volume/drivers/nimble.py b/cinder/volume/drivers/nimble.py index b0057a7112f..9958f725914 100644 --- a/cinder/volume/drivers/nimble.py +++ b/cinder/volume/drivers/nimble.py @@ -737,6 +737,28 @@ class NimbleBaseVolumeDriver(san.SanDriver): return True return False + def revert_to_snapshot(self, context, volume, snapshot): + vol_info = self.APIExecutor.get_vol_info(volume['name']) + snap_id = vol_info['last_snap']['snap_id'] + volume_id = vol_info['id'] + LOG.debug("Reverting volume %(vol)s with snapshot id %(snap_id)s", + {'vol': volume['name'], 'snap_id': snap_id}) + data = {'data': {"base_snap_id": snap_id, "id": volume_id}} + try: + self.APIExecutor.online_vol(volume['name'], False) + self.APIExecutor.volume_restore(volume['name'], data) + LOG.info("Volume %(vol)s is successfully restored with " + "snap_id %(snap_id)s", + {'vol': volume['name'], 'snap_id': snap_id}) + self.APIExecutor.online_vol(volume['name'], True) + except NimbleAPIException as ex: + raise NimbleAPIException(_("Unable to restore %(vol)s to " + "%(snap_id)s: %(err)s") % + {'vol': volume['name'], + 'snap_id': snap_id, + 'err': ex.message}) + return self._get_model_info(volume['name']) + @interface.volumedriver class NimbleISCSIDriver(NimbleBaseVolumeDriver, san.SanISCSIDriver): @@ -1846,6 +1868,11 @@ class NimbleRestAPIExecutor(object): else: raise + def volume_restore(self, volume_name, data): + volume_id = self.get_volume_id_by_name(volume_name) + api = 'volumes/%s/actions/restore' % volume_id + self.post(api, data) + @_connection_checker def get(self, api): return self.get_query(api, None) diff --git a/doc/source/configuration/block-storage/drivers/nimble-volume-driver.rst b/doc/source/configuration/block-storage/drivers/nimble-volume-driver.rst index 956e11eb948..07d7a1d3e69 100644 --- a/doc/source/configuration/block-storage/drivers/nimble-volume-driver.rst +++ b/doc/source/configuration/block-storage/drivers/nimble-volume-driver.rst @@ -38,7 +38,7 @@ Supported operations * Retype a volume * Create a Thinly Provisioned Volume * Attach a volume to multiple servers simultaneously (multiattach) - +* Volume Revert to Snapshot Nimble Storage driver configuration ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/source/reference/support-matrix.ini b/doc/source/reference/support-matrix.ini index 5a77d77ed60..6e946c789f4 100644 --- a/doc/source/reference/support-matrix.ini +++ b/doc/source/reference/support-matrix.ini @@ -832,7 +832,7 @@ driver.netapp_ontap=missing driver.netapp_solidfire=complete driver.nexenta=missing driver.nfs=missing -driver.nimble=missing +driver.nimble=complete driver.prophetstor=missing driver.pure=complete driver.qnap=missing diff --git a/releasenotes/notes/1899512-7a872a2c19e53536.yaml b/releasenotes/notes/1899512-7a872a2c19e53536.yaml new file mode 100644 index 00000000000..fa7022fdf9e --- /dev/null +++ b/releasenotes/notes/1899512-7a872a2c19e53536.yaml @@ -0,0 +1,4 @@ +--- +features: + - | + Added revert to snapshot feature in Nimble driver.