Hitachi drivers: resize volume if cloned image is larger

Extend volume if during create_volume_from_snapshot() the new volume
is larger than the image it was cloned from. Extended test cases to
cover the change.

Closes-Bug: #1554779

Change-Id: I001d40e9aaa15dfa98230a1b6902b1d24931c9af
Signed-off-by: Danny Al-Gaaf <danny.al-gaaf@bisect.de>
This commit is contained in:
Danny Al-Gaaf 2016-03-17 11:09:09 +01:00
parent fd5817881a
commit dbf7495f51
8 changed files with 128 additions and 6 deletions

View File

@ -444,6 +444,10 @@ STS : NML"
'id': 'test-volume',
'provider_location': '1', 'status': 'available'}
test_volume_larger = {'name': 'test_volume', 'size': 256,
'id': 'test-volume',
'provider_location': '1', 'status': 'available'}
test_volume_error = {'name': 'test_volume', 'size': 256,
'id': 'test-volume',
'status': 'creating'}
@ -752,6 +756,28 @@ STS : NML"
self.assertEqual('1', vol['provider_location'])
return
@mock.patch.object(hbsd_common.HBSDCommon, 'get_volume_metadata',
return_value={'dummy_volume_meta': 'meta'})
@mock.patch.object(hbsd_common.HBSDCommon, 'get_volume',
return_value=_VOLUME)
@mock.patch.object(hbsd_common.HBSDCommon, 'extend_volume')
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
@mock.patch.object(hbsd_horcm.HBSDHORCM, 'exec_raidcom',
side_effect=_exec_raidcom)
@mock.patch.object(hbsd_horcm.HBSDHORCM, 'start_horcm',
return_value=[0, "", ""])
@mock.patch.object(hbsd_horcm.HBSDHORCM, 'check_horcm',
return_value=[0, "", ""])
def test_create_cloned_volume_larger_size(self, arg1, arg2, arg3, arg4,
arg5, arg6, arg7):
"""test create_cloned_volume."""
vol = self.driver.create_cloned_volume(self.test_volume_larger,
self._VOLUME)
self.assertEqual('1', vol['provider_location'])
arg5.assert_called_once_with(self.test_volume_larger,
self.test_volume_larger['size'])
return
@mock.patch.object(hbsd_common.HBSDCommon, 'get_volume_metadata',
return_value={'dummy_volume_meta': 'meta'})
@mock.patch.object(hbsd_common.HBSDCommon, 'get_volume',

View File

@ -196,6 +196,10 @@ Host Group\n abcdefg 10000000C97BCE7A \
'id': 'test-volume-0',
'provider_location': '1', 'status': 'available'}
test_volume_larger = {'name': 'test_volume', 'size': 256,
'id': 'test-volume-0',
'provider_location': '1', 'status': 'available'}
test_volume_error = {'name': 'test_volume_error', 'size': 256,
'id': 'test-volume-error',
'provider_location': '3', 'status': 'available'}
@ -415,6 +419,22 @@ Host Group\n abcdefg 10000000C97BCE7A \
self.assertIsNotNone(vol)
return
@mock.patch.object(hbsd_common.HBSDCommon, 'get_volume_metadata',
return_value={'dummy_volume_meta': 'meta'})
@mock.patch.object(hbsd_common.HBSDCommon, 'get_volume',
return_value=_VOLUME)
@mock.patch.object(hbsd_common.HBSDCommon, 'extend_volume')
@mock.patch.object(hbsd_snm2.HBSDSNM2, 'exec_hsnm', side_effect=_exec_hsnm)
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
def test_create_cloned_volume_larger(self, arg1, arg2, arg3, arg4, arg5):
"""test create_cloned_volume."""
vol = self.driver.create_cloned_volume(self.test_volume_larger,
self._VOLUME)
self.assertIsNotNone(vol)
arg3.assert_called_once_with(self.test_volume_larger,
self.test_volume_larger['size'])
return
@mock.patch.object(hbsd_common.HBSDCommon, 'get_volume_metadata',
return_value={'dummy_volume_meta': 'meta'})
@mock.patch.object(hbsd_common.HBSDCommon, 'get_volume',

View File

@ -212,6 +212,10 @@ Authentication\n\
'id': 'test-volume-0',
'provider_location': '1', 'status': 'available'}
test_volume_larger = {'name': 'test_volume', 'size': 256,
'id': 'test-volume-0',
'provider_location': '1', 'status': 'available'}
test_volume_error = {'name': 'test_volume_error', 'size': 256,
'id': 'test-volume-error',
'provider_location': '3', 'status': 'available'}
@ -450,6 +454,22 @@ Authentication\n\
self.assertIsNotNone(vol)
return
@mock.patch.object(hbsd_common.HBSDCommon, 'get_volume_metadata',
return_value={'dummy_volume_meta': 'meta'})
@mock.patch.object(hbsd_common.HBSDCommon, 'get_volume',
return_value=_VOLUME)
@mock.patch.object(hbsd_common.HBSDCommon, 'extend_volume')
@mock.patch.object(hbsd_snm2.HBSDSNM2, 'exec_hsnm', side_effect=_exec_hsnm)
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
def test_create_cloned_volume_larger(self, arg1, arg2, arg3, arg4, arg5):
"""test create_cloned_volume."""
vol = self.driver.create_cloned_volume(self.test_volume_larger,
self._VOLUME)
self.assertIsNotNone(vol)
arg3.assert_called_once_with(self.test_volume_larger,
self.test_volume_larger['size'])
return
@mock.patch.object(hbsd_common.HBSDCommon, 'get_volume_metadata',
return_value={'dummy_volume_meta': 'meta'})
@mock.patch.object(hbsd_common.HBSDCommon, 'get_volume',

View File

@ -388,6 +388,25 @@ class HNASiSCSIDriverTest(test.TestCase):
self.backend.deleteVolumebyProvider(src_vol['provider_location'])
self.backend.deleteVolumebyProvider(loc['provider_location'])
@mock.patch.object(iscsi.HDSISCSIDriver, '_id_to_vol')
@mock.patch.object(iscsi.HDSISCSIDriver, 'extend_volume')
def test_create_clone_larger_size(self, m_extend_volume, m_id_to_vol):
src_vol = self._create_volume()
m_id_to_vol.return_value = src_vol
src_vol['volume_size'] = src_vol['size']
dst_vol = self._create_volume()
dst_vol['size'] = 256
dst_vol['volume_size'] = dst_vol['size']
loc = self.driver.create_cloned_volume(dst_vol, src_vol)
self.assertNotEqual(loc, None)
m_extend_volume.assert_called_once_with(dst_vol, 256)
# cleanup
self.backend.deleteVolumebyProvider(src_vol['provider_location'])
self.backend.deleteVolumebyProvider(loc['provider_location'])
@mock.patch.object(iscsi.HDSISCSIDriver, '_id_to_vol')
def test_delete_snapshot(self, m_id_to_vol):
svol = self._create_volume()

View File

@ -335,6 +335,30 @@ class HDSNFSDriverTest(test.TestCase):
out = "{'provider_location': \'" + _SHARE + "'}"
self.assertEqual(out, str(loc))
@mock.patch.object(nfs.HDSNFSDriver, '_get_service')
@mock.patch.object(nfs.HDSNFSDriver, '_id_to_vol', side_effect=id_to_vol)
@mock.patch.object(nfs.HDSNFSDriver, '_get_provider_location')
@mock.patch.object(nfs.HDSNFSDriver, '_get_volume_location')
@mock.patch.object(nfs.HDSNFSDriver, 'extend_volume')
def test_create_cloned_volume_larger(self, m_extend_volume,
m_get_volume_location,
m_get_provider_location,
m_id_to_vol, m_get_service):
vol = _VOLUME.copy()
svol = _SNAPVOLUME.copy()
m_get_service.return_value = _SERVICE
m_get_provider_location.return_value = _SHARE
m_get_volume_location.return_value = _SHARE
svol['size'] = 256
loc = self.driver.create_cloned_volume(svol, vol)
out = "{'provider_location': \'" + _SHARE + "'}"
self.assertEqual(out, str(loc))
m_extend_volume.assert_called_once_with(svol, svol['size'])
@mock.patch.object(nfs.HDSNFSDriver, '_ensure_shares_mounted')
@mock.patch.object(nfs.HDSNFSDriver, '_do_create_volume')
@mock.patch.object(nfs.HDSNFSDriver, '_id_to_vol', side_effect=id_to_vol)

View File

@ -644,7 +644,7 @@ class HBSDCommon(object):
self.check_volume_status(self.get_volume(src_vref['id']), is_vvol)
size = volume['size']
src_size = src_vref['size']
if size != src_size:
if size < src_size:
msg = basic_lib.output_err(617, type='volume',
volume_id=volume['id'])
raise exception.HBSDError(message=msg)
@ -652,7 +652,10 @@ class HBSDCommon(object):
metadata = self.get_volume_metadata(volume['id'])
method = None if is_vvol else self.get_copy_method(volume)
svol, type = self.copy_data(pvol, size, is_vvol, method)
svol, type = self.copy_data(pvol, src_size, is_vvol, method)
if size > src_size:
self.extend_volume(volume, size)
metadata['type'] = type
metadata['volume'] = src_vref['id']

View File

@ -579,9 +579,10 @@ class HDSISCSIDriver(driver.ISCSIDriver):
:param src: ditctionary source volume reference
"""
if src['size'] != dst['size']:
msg = 'clone volume size mismatch'
if src['size'] > dst['size']:
msg = 'Clone volume size must not be smaller than source volume'
raise exception.VolumeBackendAPIException(data=msg)
hdp = self._get_service(dst)
size = int(src['size']) * units.Ki
source_vol = self._id_to_vol(src['id'])
@ -594,7 +595,12 @@ class HDSISCSIDriver(driver.ISCSIDriver):
dst['name'])
lun = self.arid + '.' + out.split()[1]
size = int(out.split()[5])
if src['size'] < dst['size']:
size = dst['size']
self.extend_volume(dst, size)
else:
size = int(out.split()[5])
LOG.debug("LUN %(lun)s of size %(size)s MB is cloned.",
{'lun': lun, 'size': size})

View File

@ -401,13 +401,17 @@ class HDSNFSDriver(nfs.NfsDriver):
vol_size = volume['size']
src_vol_size = src_vref['size']
if vol_size != src_vol_size:
if vol_size < src_vol_size:
msg = _("Cannot create clone of size %(vol_size)s from "
"volume of size %(src_vol_size)s")
msg_fmt = {'vol_size': vol_size, 'src_vol_size': src_vol_size}
raise exception.CinderException(msg % msg_fmt)
self._clone_volume(src_vref['name'], volume['name'], src_vref['id'])
if vol_size > src_vol_size:
self.extend_volume(volume, vol_size)
share = self._get_volume_location(src_vref['id'])
return {'provider_location': share}