diff --git a/cinder/tests/unit/volume/drivers/dell_emc/test_xtremio.py b/cinder/tests/unit/volume/drivers/dell_emc/test_xtremio.py index 974e9a82f3a..728090cb117 100644 --- a/cinder/tests/unit/volume/drivers/dell_emc/test_xtremio.py +++ b/cinder/tests/unit/volume/drivers/dell_emc/test_xtremio.py @@ -266,6 +266,7 @@ class CommonData(object): test_snapshot = D() test_snapshot.update({'name': 'snapshot1', 'size': 1, + 'volume_size': 1, 'id': '192eb39b-6c2f-420c-bae3-3cfd117f0002', 'volume_name': 'vol-vol1', 'volume_id': '192eb39b-6c2f-420c-bae3-3cfd117f0001', @@ -449,6 +450,52 @@ class XtremIODriverISCSITestCase(BaseXtremIODriverTestCase): self.driver.create_volume_from_snapshot(self.data.test_volume2, self.data.test_snapshot) + def test_volume_from_snapshot_and_resize(self, req): + req.side_effect = xms_request + xms_data['volumes'] = {} + self.driver.create_volume(self.data.test_volume) + clone_volume = self.data.test_clone.copy() + clone_volume['size'] = 2 + self.driver.create_snapshot(self.data.test_snapshot) + with mock.patch.object(self.driver, + 'extend_volume') as extend: + self.driver.create_volume_from_snapshot(clone_volume, + self.data.test_snapshot) + extend.assert_called_once_with(clone_volume, clone_volume['size']) + + def test_volume_from_snapshot_and_resize_fail(self, req): + req.side_effect = xms_request + self.driver.create_volume(self.data.test_volume) + vol = xms_data['volumes'][1] + + def failed_extend(obj_type='volumes', method='GET', data=None, + *args, **kwargs): + if method == 'GET': + return {'content': vol} + elif method == 'POST': + return {'links': [{'href': 'volume/2'}]} + elif method == 'PUT': + if 'name' in data: + return + raise exception.VolumeBackendAPIException('Failed Clone') + + self.driver.create_snapshot(self.data.test_snapshot) + req.side_effect = failed_extend + self.driver.db = mock.Mock() + (self.driver.db. + image_volume_cache_get_by_volume_id.return_value) = mock.MagicMock() + clone = self.data.test_clone.copy() + clone['size'] = 2 + + with mock.patch.object(self.driver, + 'delete_volume') as delete: + self.assertRaises(exception.VolumeBackendAPIException, + self.driver.create_volume_from_snapshot, + clone, + self.data.test_snapshot) + self.assertTrue(delete.called) + + # ##### Clone Volume ##### def test_clone_volume(self, req): req.side_effect = xms_request diff --git a/cinder/volume/drivers/dell_emc/xtremio.py b/cinder/volume/drivers/dell_emc/xtremio.py index bac055a0a1d..22d763216cb 100644 --- a/cinder/volume/drivers/dell_emc/xtremio.py +++ b/cinder/volume/drivers/dell_emc/xtremio.py @@ -488,7 +488,22 @@ class XtremIOVolumeDriver(san.SanDriver): else: snapshot_id = snapshot['id'] - self.client.create_snapshot(snapshot_id, volume['id']) + try: + self.client.create_snapshot(snapshot_id, volume['id']) + except exception.XtremIOSnapshotsLimitExceeded as e: + raise exception.CinderException(e.message) + + # extend the snapped volume if requested size is larger then original + if volume['size'] > snapshot['volume_size']: + try: + self.extend_volume(volume, volume['size']) + except Exception: + LOG.error('failed to extend volume %s, ' + 'reverting volume from snapshot operation', + volume['id']) + # remove the volume in case resize failed + self.delete_volume(volume) + raise # add new volume to consistency group if (volume.get('consistencygroup_id') and @@ -516,7 +531,7 @@ class XtremIOVolumeDriver(san.SanDriver): try: self.extend_volume(volume, volume['size']) except Exception: - LOG.error('failes to extend volume %s, ' + LOG.error('failed to extend volume %s, ' 'reverting clone operation', volume['id']) # remove the volume in case resize failed self.delete_volume(volume) @@ -807,7 +822,10 @@ class XtremIOVolumeDriver(san.SanDriver): snap_by_anc = self._get_snapset_ancestors(snap_name) for volume, snapshot in zip(volumes, snapshots): real_snap = snap_by_anc[snapshot['volume_id']] - self.create_volume_from_snapshot(volume, {'id': real_snap}) + self.create_volume_from_snapshot( + volume, + {'id': real_snap, + 'volume_size': snapshot['volume_size']}) elif source_cg: data = {'consistency-group-id': source_cg['id'],