From 7f44844cc103ac61940cebd89f7835c971ee0ffc Mon Sep 17 00:00:00 2001 From: Shay Halsband Date: Thu, 7 Jul 2016 17:17:37 +0300 Subject: [PATCH] XtremIO: support of snapshot manage commands As snapshots are volumes in XtremIO, all this change does is route the snapshot manage calls to the appropriate volume manage calls. DocImpact Change-Id: I90432ace52d9c8b7ae48c843be86c1d51e8c875e Implements: blueprint xtremio-manage-snapshot --- cinder/tests/unit/test_emc_xtremio.py | 59 +++++++++++++++++++ cinder/volume/drivers/emc/xtremio.py | 38 +++++++++--- ...emio-manage-snapshot-5737d3ad37df81d1.yaml | 3 + 3 files changed, 92 insertions(+), 8 deletions(-) create mode 100644 releasenotes/notes/xtremio-manage-snapshot-5737d3ad37df81d1.yaml diff --git a/cinder/tests/unit/test_emc_xtremio.py b/cinder/tests/unit/test_emc_xtremio.py index e8ec06501cc..92f48c2b5ab 100644 --- a/cinder/tests/unit/test_emc_xtremio.py +++ b/cinder/tests/unit/test_emc_xtremio.py @@ -673,6 +673,65 @@ class EMCXIODriverISCSITestCase(BaseEMCXIODriverTestCase): self.assertRaises(exception.VolumeNotFound, self.driver.unmanage, self.data.test_volume2) + def test_manage_snapshot(self, req): + req.side_effect = xms_request + vol_uid = self.data.test_snapshot.volume_id + xms_data['volumes'] = {1: {'name': vol_uid, + 'index': 1, + 'vol-size': '3', + }, + 2: {'name': 'unmanaged', + 'index': 2, + 'ancestor-vol-id': ['', vol_uid, 1], + 'vol-size': '3'} + } + ref_vol = {"source-name": "unmanaged"} + self.driver.manage_existing_snapshot(self.data.test_snapshot, ref_vol) + + def test_get_manage_snapshot_size(self, req): + req.side_effect = xms_request + vol_uid = self.data.test_snapshot.volume_id + xms_data['volumes'] = {1: {'name': vol_uid, + 'index': 1, + 'vol-size': '3', + }, + 2: {'name': 'unmanaged', + 'index': 2, + 'ancestor-vol-id': ['', vol_uid, 1], + 'vol-size': '3'} + } + ref_vol = {"source-name": "unmanaged"} + self.driver.manage_existing_snapshot_get_size(self.data.test_snapshot, + ref_vol) + + def test_manage_snapshot_invalid_snapshot(self, req): + req.side_effect = xms_request + xms_data['volumes'] = {1: {'name': 'unmanaged1', + 'index': 1, + 'vol-size': '3', + 'ancestor-vol-id': []} + } + ref_vol = {"source-name": "unmanaged1"} + self.assertRaises(exception.ManageExistingInvalidReference, + self.driver.manage_existing_snapshot, + self.data.test_snapshot, ref_vol) + + def test_unmanage_snapshot(self, req): + req.side_effect = xms_request + vol_uid = self.data.test_snapshot.volume_id + xms_data['volumes'] = {1: {'name': vol_uid, + 'index': 1, + 'vol-size': '3', + }, + 2: {'name': 'unmanaged', + 'index': 2, + 'ancestor-vol-id': ['', vol_uid, 1], + 'vol-size': '3'} + } + ref_vol = {"source-name": "unmanaged"} + self.driver.manage_existing_snapshot(self.data.test_snapshot, ref_vol) + self.driver.unmanage_snapshot(self.data.test_snapshot) + # ##### Consistancy Groups ##### @mock.patch('cinder.objects.snapshot.SnapshotList.get_all_for_cgsnapshot') def test_cg_create(self, get_all_for_cgsnapshot, req): diff --git a/cinder/volume/drivers/emc/xtremio.py b/cinder/volume/drivers/emc/xtremio.py index 5d7b503f6a9..2667e6fef4f 100644 --- a/cinder/volume/drivers/emc/xtremio.py +++ b/cinder/volume/drivers/emc/xtremio.py @@ -502,22 +502,33 @@ class XtremIOVolumeDriver(san.SanDriver): self._update_volume_stats() return self._stats - def manage_existing(self, volume, existing_ref): + def manage_existing(self, volume, existing_ref, is_snapshot=False): """Manages an existing LV.""" lv_name = existing_ref['source-name'] # Attempt to locate the volume. try: vol_obj = self.client.req('volumes', name=lv_name)['content'] + if ( + is_snapshot and + (not vol_obj['ancestor-vol-id'] or + vol_obj['ancestor-vol-id'][XTREMIO_OID_NAME] != + volume.volume_id)): + kwargs = {'existing_ref': lv_name, + 'reason': 'Not a snapshot of vol %s' % + volume.volume_id} + raise exception.ManageExistingInvalidReference(**kwargs) except exception.NotFound: kwargs = {'existing_ref': lv_name, - 'reason': 'Specified logical volume does not exist.'} + 'reason': 'Specified logical %s does not exist.' % + 'snapshot' if is_snapshot else 'volume'} raise exception.ManageExistingInvalidReference(**kwargs) # Attempt to rename the LV to match the OpenStack internal name. self.client.req('volumes', 'PUT', data={'vol-name': volume['id']}, idx=vol_obj['index']) - def manage_existing_get_size(self, volume, existing_ref): + def manage_existing_get_size(self, volume, existing_ref, + is_snapshot=False): """Return size of an existing LV for manage_existing.""" # Check that the reference is valid if 'source-name' not in existing_ref: @@ -530,7 +541,8 @@ class XtremIOVolumeDriver(san.SanDriver): vol_obj = self.client.req('volumes', name=lv_name)['content'] except exception.NotFound: kwargs = {'existing_ref': lv_name, - 'reason': 'Specified logical volume does not exist.'} + 'reason': 'Specified logical %s does not exist.' % + 'snapshot' if is_snapshot else 'volume'} raise exception.ManageExistingInvalidReference(**kwargs) # LV size is returned in gigabytes. Attempt to parse size as a float # and round up to the next integer. @@ -538,18 +550,28 @@ class XtremIOVolumeDriver(san.SanDriver): return lv_size - def unmanage(self, volume): + def unmanage(self, volume, is_snapshot=False): """Removes the specified volume from Cinder management.""" # trying to rename the volume to [cinder name]-unmanged try: self.client.req('volumes', 'PUT', name=volume['id'], data={'vol-name': volume['name'] + '-unmanged'}) except exception.NotFound: - LOG.info(_LI("Volume with the name %s wasn't found," - " can't unmanage"), - volume['id']) + LOG.info(_LI("%(typ)s with the name %(name)s wasn't found, " + "can't unmanage") % + {'typ': 'Snapshot' if is_snapshot else 'Volume', + 'name': volume['id']}) raise exception.VolumeNotFound(volume_id=volume['id']) + def manage_existing_snapshot(self, snapshot, existing_ref): + self.manage_existing(snapshot, existing_ref, True) + + def manage_existing_snapshot_get_size(self, snapshot, existing_ref): + return self.manage_existing_get_size(snapshot, existing_ref, True) + + def unmanage_snapshot(self, snapshot): + self.unmanage(snapshot, True) + def extend_volume(self, volume, new_size): """Extend an existing volume's size.""" data = {'vol-size': six.text_type(new_size) + 'g'} diff --git a/releasenotes/notes/xtremio-manage-snapshot-5737d3ad37df81d1.yaml b/releasenotes/notes/xtremio-manage-snapshot-5737d3ad37df81d1.yaml new file mode 100644 index 00000000000..7363172dffa --- /dev/null +++ b/releasenotes/notes/xtremio-manage-snapshot-5737d3ad37df81d1.yaml @@ -0,0 +1,3 @@ +--- +features: + - Added snapshot manage/unmanage support to the EMC XtremIO driver.