Infinidat: add support for revert to snapshot operation

Adding support to revert a volume to a snapshot in Infinidat driver.
This patch implements:
- revert_to_snapshot()
- snapshot_revert_use_temp_snapshot()

Implements: blueprint infinidat-add-snapshot-revert
Change-Id: I7d3e639b896604a09c4e8a9fc24ab8aff1f65622
Signed-off-by: Alexander Deiter <adeiter@infinidat.com>
This commit is contained in:
Alexander Deiter 2022-07-06 17:14:04 +04:00
parent 55239a7fc0
commit 2c25e2259e
5 changed files with 56 additions and 2 deletions

View File

@ -14,11 +14,13 @@
# under the License. # under the License.
"""Unit tests for INFINIDAT InfiniBox volume driver.""" """Unit tests for INFINIDAT InfiniBox volume driver."""
import copy
import functools import functools
import platform import platform
import socket import socket
from unittest import mock from unittest import mock
import ddt
from oslo_utils import units from oslo_utils import units
from cinder import exception from cinder import exception
@ -122,6 +124,7 @@ class InfiniboxDriverTestCaseBase(test.TestCase):
self._mock_volume.has_children.return_value = False self._mock_volume.has_children.return_value = False
self._mock_volume.get_logical_units.return_value = [] self._mock_volume.get_logical_units.return_value = []
self._mock_volume.create_snapshot.return_value = self._mock_volume self._mock_volume.create_snapshot.return_value = self._mock_volume
self._mock_snapshot = mock.Mock()
self._mock_host = mock.Mock() self._mock_host = mock.Mock()
self._mock_host.get_luns.return_value = [] self._mock_host.get_luns.return_value = []
self._mock_host.map_volume().get_lun.return_value = TEST_LUN self._mock_host.map_volume().get_lun.return_value = TEST_LUN
@ -157,6 +160,7 @@ class InfiniboxDriverTestCaseBase(test.TestCase):
raise FakeInfinisdkException() raise FakeInfinisdkException()
@ddt.ddt
class InfiniboxDriverTestCase(InfiniboxDriverTestCaseBase): class InfiniboxDriverTestCase(InfiniboxDriverTestCaseBase):
def _generate_mock_object_metadata(self, cinder_object): def _generate_mock_object_metadata(self, cinder_object):
return {"system": "openstack", return {"system": "openstack",
@ -597,6 +601,29 @@ class InfiniboxDriverTestCase(InfiniboxDriverTestCaseBase):
self._mock_host.unmap_volume.assert_called_once() self._mock_host.unmap_volume.assert_called_once()
self._mock_host.safe_delete.assert_called_once() self._mock_host.safe_delete.assert_called_once()
def test_snapshot_revert_use_temp_snapshot(self):
result = self.driver.snapshot_revert_use_temp_snapshot()
self.assertFalse(result)
@ddt.data((1, 1), (1, 2))
@ddt.unpack
def test_revert_to_snapshot_resize(self, volume_size, snapshot_size):
volume = copy.deepcopy(test_volume)
snapshot = copy.deepcopy(test_snapshot)
snapshot.volume.size = snapshot_size
self._system.volumes.safe_get.side_effect = [self._mock_snapshot,
self._mock_volume,
self._mock_volume]
self._mock_volume.get_size.side_effect = [volume_size * units.Gi,
volume_size * units.Gi]
self.driver.revert_to_snapshot(None, volume, snapshot)
self._mock_volume.restore.assert_called_once_with(self._mock_snapshot)
if volume_size == snapshot_size:
self._mock_volume.resize.assert_not_called()
else:
delta = (snapshot_size - volume_size) * units.Gi
self._mock_volume.resize.assert_called_with(delta)
class InfiniboxDriverTestCaseFC(InfiniboxDriverTestCaseBase): class InfiniboxDriverTestCaseFC(InfiniboxDriverTestCaseBase):
def test_initialize_connection_multiple_wwpns(self): def test_initialize_connection_multiple_wwpns(self):

View File

@ -118,10 +118,11 @@ class InfiniboxVolumeDriver(san.SanISCSIDriver):
1.5 - added support for volume compression 1.5 - added support for volume compression
1.6 - added support for volume multi-attach 1.6 - added support for volume multi-attach
1.7 - fixed iSCSI to return all portals 1.7 - fixed iSCSI to return all portals
1.8 - added revert to snapshot
""" """
VERSION = '1.7' VERSION = '1.8'
# ThirdPartySystems wiki page # ThirdPartySystems wiki page
CI_WIKI_NAME = "INFINIDAT_CI" CI_WIKI_NAME = "INFINIDAT_CI"
@ -837,3 +838,24 @@ class InfiniboxVolumeDriver(san.SanISCSIDriver):
for snapshot in snapshots: for snapshot in snapshots:
self.delete_snapshot(snapshot) self.delete_snapshot(snapshot)
return None, None return None, None
def snapshot_revert_use_temp_snapshot(self):
"""Disable the use of a temporary snapshot on revert."""
return False
@infinisdk_to_cinder_exceptions
def revert_to_snapshot(self, context, volume, snapshot):
"""Revert volume to snapshot.
Note: the revert process should not change the volume's
current size, that means if the driver shrank
the volume during the process, it should extend the
volume internally.
"""
infinidat_snapshot = self._get_infinidat_snapshot(snapshot)
infinidat_volume = self._get_infinidat_volume(snapshot.volume)
infinidat_volume.restore(infinidat_snapshot)
volume_size = infinidat_volume.get_size()
snapshot_size = snapshot.volume.size * capacity.GiB
if volume_size < snapshot_size:
self.extend_volume(volume, snapshot.volume.size)

View File

@ -22,6 +22,7 @@ Supported operations
* Create, modify, delete, and list snapshots of consistency groups. * Create, modify, delete, and list snapshots of consistency groups.
* Create consistency group from consistency group or consistency group * Create consistency group from consistency group or consistency group
snapshot. snapshot.
* Revert a volume to a snapshot.
External package installation External package installation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -875,7 +875,7 @@ driver.huawei_v5=missing
driver.huawei_18000=missing driver.huawei_18000=missing
driver.huawei_dorado=missing driver.huawei_dorado=missing
driver.huawei_fusionstorage=missing driver.huawei_fusionstorage=missing
driver.infinidat=missing driver.infinidat=complete
driver.ibm_ds8k=complete driver.ibm_ds8k=complete
driver.ibm_flashsystem=missing driver.ibm_flashsystem=missing
driver.ibm_gpfs=missing driver.ibm_gpfs=missing

View File

@ -0,0 +1,4 @@
---
features:
- |
Infinidat driver: Added support for revert to snapshot operation.