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:
parent
62da0d6f60
commit
01971c9cb6
@ -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):
|
||||
|
@ -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
|
||||
|
@ -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.")
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
|
||||
|
@ -0,0 +1,5 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Added support for revert-to-snapshot in the VMware VMDK driver.
|
||||
|
Loading…
Reference in New Issue
Block a user