VMware: Revert to snapshot

Adding support for revert-to-snapshot for COW based snapshot
in VMDK driver.

Change-Id: I240d8d6f1745f9611855e6f6897697b5a0748ef9
This commit is contained in:
Vipin Balachandran 2017-08-21 18:04:57 -07:00
parent 62da0d6f60
commit 01971c9cb6
6 changed files with 107 additions and 0 deletions

View File

@ -3051,6 +3051,48 @@ class VMwareVcVmdkDriverTestCase(test.TestCase):
vops.move_backing_to_folder.assert_called_once_with(backing,
new_folder)
@mock.patch.object(VMDK_DRIVER, 'volumeops')
def test_revert_to_snapshot_with_no_backing(self, vops):
vops.get_backing.return_value = None
volume = self._create_volume_obj()
snapshot = fake_snapshot.fake_snapshot_obj(self._context,
volume=volume)
self._driver.revert_to_snapshot(
mock.sentinel.context, volume, snapshot)
vops.get_backing.assert_called_once_with(volume.name)
vops.revert_to_snapshot.assert_not_called()
@mock.patch.object(VMDK_DRIVER, 'volumeops')
def test_revert_to_snapshot_template_format(self, vops):
volume = self._create_volume_obj()
loc = '/test-dc/foo'
snapshot = fake_snapshot.fake_snapshot_obj(self._context,
volume=volume,
provider_location=loc)
self.assertRaises(cinder_exceptions.InvalidSnapshot,
self._driver.revert_to_snapshot,
mock.sentinel.context,
volume,
snapshot)
vops.revert_to_snapshot.assert_not_called()
@mock.patch.object(VMDK_DRIVER, 'volumeops')
def test_revert_to_snapshot(self, vops):
backing = mock.sentinel.backing
vops.get_backing.return_value = backing
volume = self._create_volume_obj()
snapshot = fake_snapshot.fake_snapshot_obj(self._context,
volume=volume)
self._driver.revert_to_snapshot(
mock.sentinel.context, volume, snapshot)
vops.get_backing.assert_called_once_with(volume.name)
vops.revert_to_snapshot.assert_called_once_with(backing,
snapshot.name)
@ddt.ddt
class ImageDiskTypeTest(test.TestCase):

View File

@ -947,6 +947,33 @@ class VolumeOpsTestCase(test.TestCase):
snapshot, removeChildren=False)
self.session.wait_for_task.assert_called_once_with(task)
@mock.patch('cinder.volume.drivers.vmware.volumeops.VMwareVolumeOps.'
'get_snapshot')
def test_revert_to_snapshot_with_missing_snapshot(self, get_snapshot):
get_snapshot.return_value = None
backing = mock.sentinel.backing
self.assertRaises(vmdk_exceptions.SnapshotNotFoundException,
self.vops.revert_to_snapshot, backing, 'foo')
get_snapshot.assert_called_once_with(backing, 'foo')
@mock.patch('cinder.volume.drivers.vmware.volumeops.VMwareVolumeOps.'
'get_snapshot')
def test_revert_to_snapshot(self, get_snapshot):
snapshot = mock.sentinel.snapshot
get_snapshot.return_value = snapshot
task = mock.sentinel.task
self.session.invoke_api.return_value = task
backing = mock.sentinel.backing
self.vops.revert_to_snapshot(backing, 'foo')
get_snapshot.assert_called_once_with(backing, 'foo')
self.session.invoke_api.assert_called_once_with(
self.session.vim, 'RevertToSnapshot_Task', snapshot)
self.session.wait_for_task.assert_called_once_with(task)
def test_get_folder(self):
folder = mock.sentinel.folder
backing = mock.sentinel.backing

View File

@ -60,3 +60,8 @@ class NoValidHostException(exceptions.VMwareDriverException):
class TemplateNotFoundException(exceptions.VMwareDriverException):
"""Thrown when template cannot be found."""
msg_fmt = _("Template cannot be found at path: %(path)s.")
class SnapshotNotFoundException(exceptions.VMwareDriverException):
"""Thrown when the backend snapshot cannot be found."""
msg_fmt = _("Snapshot: %(name)s not found.")

View File

@ -2142,3 +2142,17 @@ class VMwareVcVmdkDriver(driver.VolumeDriver):
dc = self.volumeops.get_dc(backing)
new_folder = self._get_volume_group_folder(dc, new_project)
self.volumeops.move_backing_to_folder(backing, new_folder)
def revert_to_snapshot(self, context, volume, snapshot):
inv_path = snapshot.provider_location
is_template = inv_path is not None
if is_template:
LOG.error("Revert to template based snapshot is not supported.")
raise exception.InvalidSnapshot("Cannot revert to template "
"based snapshot")
backing = self.volumeops.get_backing(volume.name)
if not backing:
LOG.debug("Backing does not exist for volume.", resource=volume)
else:
self.volumeops.revert_to_snapshot(backing, snapshot.name)

View File

@ -1048,6 +1048,20 @@ class VMwareVolumeOps(object):
LOG.info("Successfully deleted snapshot: %(name)s of backing: "
"%(backing)s.", {'backing': backing, 'name': name})
def revert_to_snapshot(self, backing, name):
LOG.debug("Revert to snapshot: %(name)s of backing: %(backing)s.",
{'name': name, 'backing': backing})
snapshot = self.get_snapshot(backing, name)
if not snapshot:
raise vmdk_exceptions.SnapshotNotFoundException(
name=name)
task = self._session.invoke_api(self._session.vim,
'RevertToSnapshot_Task',
snapshot)
self._session.wait_for_task(task)
def _get_folder(self, backing):
"""Get parent folder of the backing.

View File

@ -0,0 +1,5 @@
---
features:
- |
Added support for revert-to-snapshot in the VMware VMDK driver.