Browse Source

Merge "Add revert to snapshot support in VxFlex OS driver"

tags/16.0.0.0rc1
Zuul 3 months ago
committed by Gerrit Code Review
parent
commit
c3c7a6328e
6 changed files with 157 additions and 2 deletions
  1. +104
    -0
      cinder/tests/unit/volume/drivers/dell_emc/vxflexos/test_revert_volume_to_snapshot.py
  2. +29
    -1
      cinder/volume/drivers/dell_emc/vxflexos/driver.py
  3. +17
    -0
      cinder/volume/drivers/dell_emc/vxflexos/rest_client.py
  4. +2
    -0
      doc/source/configuration/block-storage/drivers/dell-emc-vxflex-driver.rst
  5. +1
    -1
      doc/source/reference/support-matrix.ini
  6. +4
    -0
      releasenotes/notes/vxflexos-revert-to-snapshot-a90c40ec476cc2bd.yaml

+ 104
- 0
cinder/tests/unit/volume/drivers/dell_emc/vxflexos/test_revert_volume_to_snapshot.py View File

@@ -0,0 +1,104 @@
# Copyright (c) 2020 Dell Inc. or its subsidiaries.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

from unittest import mock

from cinder import context
from cinder import exception
from cinder.tests.unit import fake_constants as fake
from cinder.tests.unit import fake_snapshot
from cinder.tests.unit import fake_volume
from cinder.tests.unit.volume.drivers.dell_emc import vxflexos


class TestRevertVolume(vxflexos.TestVxFlexOSDriver):
"""Test cases for ``VxFlexOSDriver.revert_to_snapshot()``"""

def setUp(self):
"""Setup a test case environment.

Creates a fake volume object and sets up the required API responses.
"""

super(TestRevertVolume, self).setUp()
ctx = context.RequestContext('fake', 'fake', auth_token=True)
host = 'host@backend#{}:{}'.format(
self.PROT_DOMAIN_NAME,
self.STORAGE_POOL_NAME)
self.volume = fake_volume.fake_volume_obj(
ctx, **{'provider_id': fake.PROVIDER_ID, 'host': host,
'volume_type_id': fake.VOLUME_TYPE_ID,
'size': 8})
self.snapshot = fake_snapshot.fake_snapshot_obj(
ctx, **{'volume_id': self.volume.id,
'volume_size': self.volume.size}
)
self.HTTPS_MOCK_RESPONSES = {
self.RESPONSE_MODE.Valid: {
'instances/Volume::{}/action/overwriteVolumeContent'.format(
self.volume.provider_id
): {},
},
self.RESPONSE_MODE.Invalid: {
'version': "2.6",
},
self.RESPONSE_MODE.BadStatus: {
'instances/Volume::{}/action/overwriteVolumeContent'.format(
self.volume.provider_id
): self.BAD_STATUS_RESPONSE
},
}

self.volume_is_replicated_mock = self.mock_object(
self.volume, 'is_replicated',
return_value=False
)

def test_revert_to_snapshot(self):
self.driver.revert_to_snapshot(None, self.volume, self.snapshot)

def test_revert_to_snapshot_badstatus_response(self):
self.set_https_response_mode(self.RESPONSE_MODE.BadStatus)
self.assertRaises(exception.VolumeBackendAPIException,
self.driver.revert_to_snapshot,
None, self.volume, self.snapshot)

def test_revert_to_snapshot_use_generic(self):
self.set_https_response_mode(self.RESPONSE_MODE.Invalid)
self.assertRaises(NotImplementedError,
self.driver.revert_to_snapshot,
None, self.volume, self.snapshot)

def test_revert_to_snapshot_replicated_volume(self):
self.volume_is_replicated_mock.return_value = True
self.assertRaisesRegexp(
exception.InvalidVolume,
'Reverting replicated volume is not allowed.',
self.driver.revert_to_snapshot,
None, self.volume, self.snapshot
)

def test_revert_to_snapshot_size_not_equal(self):
patched_volume = mock.MagicMock()
patched_volume.id = self.volume.id
patched_volume.size = 16
patched_volume.is_replicated.return_value = False
self.assertRaisesRegexp(
exception.InvalidVolume,
('Volume %s size is not equal to snapshot %s size.' %
(self.volume.id, self.snapshot.id)),
self.driver.revert_to_snapshot,
None, patched_volume, self.snapshot
)

+ 29
- 1
cinder/volume/drivers/dell_emc/vxflexos/driver.py View File

@@ -89,9 +89,10 @@ class VxFlexOSDriver(driver.VolumeDriver):
3.5.0 - Add support for VxFlex OS 3.5.x
3.5.1 - Add volume replication v2.1 support for VxFlex OS 3.5.x
3.5.2 - Add volume migration support
3.5.3 - Add revert volume to snapshot support
"""

VERSION = "3.5.2"
VERSION = "3.5.3"
# ThirdPartySystems wiki
CI_WIKI_NAME = "DellEMC_VxFlexOS_CI"

@@ -1502,6 +1503,33 @@ class VxFlexOSDriver(driver.VolumeDriver):
location = new_volume.provider_location
return {"_name_id": name_id, "provider_location": location}

def revert_to_snapshot(self, context, volume, snapshot):
"""Revert VxFlex OS volume to the specified snapshot."""

LOG.info("Revert volume %(vol_id)s to snapshot %(snap_id)s.",
{"vol_id": volume.id, "snap_id": snapshot.id})

client = self._get_client()

if not flex_utils.version_gte(client.query_rest_api_version(), "3.0"):
LOG.debug("VxFlex OS versions less than v3.0 do not "
"support reverting volume to snapshot. "
"Falling back to generic revert to snapshot method.")
raise NotImplementedError
elif volume.is_replicated():
msg = _("Reverting replicated volume is not allowed.")
LOG.error(msg)
raise exception.InvalidVolume(reason=msg)
elif snapshot.volume_size != volume.size:
msg = (_("Volume %(vol_id)s size is not equal to snapshot "
"%(snap_id)s size. Revert to snapshot operation is not "
"allowed.") %
{"vol_id": volume.id, "snap_id": snapshot.id})
LOG.error(msg)
raise exception.InvalidVolume(reason=msg)

client.overwrite_volume_content(volume, snapshot)

def _query_vxflexos_volume(self, volume, existing_ref):
type_id = volume.get("volume_type_id")
if "source-id" not in existing_ref:


+ 17
- 0
cinder/volume/drivers/dell_emc/vxflexos/rest_client.py View File

@@ -686,3 +686,20 @@ class RestClient(object):
LOG.error(msg)
raise exception.VolumeBackendAPIException(msg)
return response

def overwrite_volume_content(self, volume, snapshot):
url = "/instances/Volume::%(vol_id)s/action/overwriteVolumeContent"

params = {"srcVolumeId": snapshot.provider_id}
r, response = self.execute_vxflexos_post_request(
url,
params=params,
vol_id=volume.provider_id
)
if r.status_code != http_client.OK:
msg = (_("Failed to revert volume %(vol_id)s to snapshot "
"%(snap_id)s: %(err)s.") % {"vol_id": volume.id,
"snap_id": snapshot.id,
"err": response["message"]})
LOG.error(msg)
raise exception.VolumeBackendAPIException(msg)

+ 2
- 0
doc/source/configuration/block-storage/drivers/dell-emc-vxflex-driver.rst View File

@@ -73,6 +73,8 @@ Supported operations

* Create a volume from a snapshot

* Revert a volume to a snapshot

* Copy an image to a volume

* Copy a volume to an image


+ 1
- 1
doc/source/reference/support-matrix.ini View File

@@ -774,7 +774,7 @@ driver.dell_emc_unity=complete
driver.dell_emc_vmax_af=complete
driver.dell_emc_vmax_3=complete
driver.dell_emc_vnx=complete
driver.dell_emc_vxflexos=missing
driver.dell_emc_vxflexos=complete
driver.dell_emc_xtremio=missing
driver.fujitsu_eternus=missing
driver.hpe_3par=complete


+ 4
- 0
releasenotes/notes/vxflexos-revert-to-snapshot-a90c40ec476cc2bd.yaml View File

@@ -0,0 +1,4 @@
---
features:
- |
VxFlex OS driver now supports storage-assisted revert volume to snapshot.

Loading…
Cancel
Save