Merge "Fujitsu Driver: Improve create snapshot"

This commit is contained in:
Zuul 2024-07-31 21:42:01 +00:00 committed by Gerrit Code Review
commit 0c871f587a
5 changed files with 175 additions and 120 deletions

View File

@ -140,6 +140,7 @@ FAKE_LUN_NO1 = '0x0014'
# Snapshot1 in pool abcd1234_OSVD
FAKE_LUN_ID2 = '600000E00D2A0000002A0115001E0000'
FAKE_LUN_NO2 = '0x001E'
FAKE_SDV_NO = '0x001E'
# Volume2 in pool abcd1234_RG
FAKE_LUN_ID3 = '600000E00D2800000028075301140000'
FAKE_LUN_NO3 = '0x0114'
@ -179,7 +180,7 @@ FAKE_POOLS = [{
}]
FAKE_STATS = {
'driver_version': '1.4.4',
'driver_version': '1.4.5',
'storage_protocol': 'iSCSI',
'vendor_name': 'FUJITSU',
'QoS_support': True,
@ -189,7 +190,7 @@ FAKE_STATS = {
'pools': FAKE_POOLS,
}
FAKE_STATS2 = {
'driver_version': '1.4.4',
'driver_version': '1.4.5',
'storage_protocol': 'FC',
'vendor_name': 'FUJITSU',
'QoS_support': True,
@ -302,7 +303,14 @@ FAKE_LOCATION2 = {
'vol_name': 'FJosv_OgEZj1mSvKRvIKOExKktlg=='
}
FAKE_SNAP_META = {
'FJ_Pool_Name': 'abcd1234_OSVD',
'FJ_SDV_Name': u'FJosv_OgEZj1mSvKRvIKOExKktlg==',
'FJ_SDV_No': FAKE_SDV_NO,
}
FAKE_SNAP_INFO = {
'metadata': FAKE_SNAP_META,
'provider_location': str(FAKE_LOCATION2)
}
@ -1105,6 +1113,10 @@ class FJFCDriverTestCase(test.TestCase):
conn = FakeEternusConnection()
return conn
def volume_update(self, volume, diction):
for key, value in diction.items():
volume[key] = value
def test_get_volume_stats(self):
ret = self.driver.get_volume_stats(True)
@ -1112,9 +1124,11 @@ class FJFCDriverTestCase(test.TestCase):
def test_create_and_delete_volume(self):
model_info = self.driver.create_volume(TEST_VOLUME)
self.volume_update(TEST_VOLUME, model_info)
self.assertEqual(FAKE_MODEL_INFO1, model_info)
model_info = self.driver.create_volume(TEST_VOLUME2)
self.volume_update(TEST_VOLUME2, model_info)
self.assertEqual(FAKE_MODEL_INFO3, model_info)
self.driver.delete_volume(TEST_VOLUME)
@ -1137,6 +1151,7 @@ class FJFCDriverTestCase(test.TestCase):
'data': fake_mapdata}
model_info = self.driver.create_volume(TEST_VOLUME)
self.volume_update(TEST_VOLUME, model_info)
self.assertEqual(FAKE_MODEL_INFO1, model_info)
info = self.driver.initialize_connection(TEST_VOLUME,
@ -1157,9 +1172,11 @@ class FJFCDriverTestCase(test.TestCase):
def test_create_and_delete_snapshot(self):
model_info = self.driver.create_volume(TEST_VOLUME)
self.volume_update(TEST_VOLUME, model_info)
self.assertEqual(FAKE_MODEL_INFO1, model_info)
snap_info = self.driver.create_snapshot(TEST_SNAP)
self.volume_update(TEST_SNAP, snap_info)
self.assertEqual(FAKE_SNAP_INFO, snap_info)
self.driver.delete_snapshot(TEST_SNAP)
@ -1167,13 +1184,16 @@ class FJFCDriverTestCase(test.TestCase):
def test_create_volume_from_snapshot(self):
model_info = self.driver.create_volume(TEST_VOLUME)
self.volume_update(TEST_VOLUME, model_info)
self.assertEqual(FAKE_MODEL_INFO1, model_info)
snap_info = self.driver.create_snapshot(TEST_SNAP)
self.volume_update(TEST_SNAP, snap_info)
self.assertEqual(FAKE_SNAP_INFO, snap_info)
model_info = self.driver.create_volume_from_snapshot(TEST_CLONE,
TEST_SNAP)
self.volume_update(TEST_CLONE, model_info)
self.assertEqual(FAKE_MODEL_INFO2, model_info)
self.driver.delete_snapshot(TEST_SNAP)
@ -1182,9 +1202,11 @@ class FJFCDriverTestCase(test.TestCase):
def test_create_cloned_volume(self):
model_info = self.driver.create_volume(TEST_VOLUME)
self.volume_update(TEST_VOLUME, model_info)
self.assertEqual(FAKE_MODEL_INFO1, model_info)
model_info = self.driver.create_cloned_volume(TEST_CLONE, TEST_VOLUME)
self.volume_update(TEST_CLONE, model_info)
self.assertEqual(FAKE_MODEL_INFO2, model_info)
self.driver.delete_volume(TEST_CLONE)
@ -1195,60 +1217,34 @@ class FJFCDriverTestCase(test.TestCase):
# ThinProvisioningPool separately.
TEST_VOLUME_LIST = [TEST_VOLUME, TEST_VOLUME2]
FAKE_MODEL_INFO_LIST = [FAKE_MODEL_INFO1, FAKE_MODEL_INFO3]
model_info_list = []
for i in range(len(TEST_VOLUME_LIST)):
model_info = self.driver.create_volume(TEST_VOLUME_LIST[i])
self.volume_update(TEST_VOLUME_LIST[i], model_info)
self.assertEqual(FAKE_MODEL_INFO_LIST[i], model_info)
model_info_list.append(model_info)
for i in range(len(TEST_VOLUME_LIST)):
volume_info = {}
for key in TEST_VOLUME_LIST[i]:
if key == 'provider_location':
volume_info[key] = model_info_list[i][key]
elif key == 'metadata':
volume_info[key] = model_info_list[i][key]
else:
volume_info[key] = TEST_VOLUME_LIST[i][key]
self.driver.extend_volume(volume_info, 10)
self.driver.extend_volume(TEST_VOLUME_LIST[i], 10)
def test_create_volume_with_qos(self):
self.driver.common._get_qos_specs = mock.Mock()
self.driver.common._get_qos_specs.return_value = {'maxBWS': '700'}
self.driver.common._set_qos = mock.Mock()
model_info = self.driver.create_volume(TEST_VOLUME_QOS)
self.volume_update(TEST_VOLUME, model_info)
self.assertEqual(FAKE_MODEL_INFO_QOS, model_info)
self.driver.common._set_qos.assert_called()
def test_update_migrated_volume(self):
model_info = self.driver.create_volume(TEST_VOLUME)
self.volume_update(TEST_VOLUME, model_info)
self.assertEqual(FAKE_MODEL_INFO1, model_info)
volume_info = {}
for key in TEST_VOLUME:
if key == 'provider_location':
volume_info[key] = model_info[key]
elif key == 'metadata':
volume_info[key] = model_info[key]
else:
volume_info[key] = TEST_VOLUME[key]
model_info2 = self.driver.create_volume(TEST_VOLUME2)
self.volume_update(TEST_VOLUME2, model_info2)
self.assertEqual(FAKE_MODEL_INFO3, model_info2)
volume_info2 = {}
for key in TEST_VOLUME:
if key == 'provider_location':
volume_info2[key] = model_info2[key]
elif key == 'metadata':
volume_info2[key] = model_info2[key]
else:
volume_info2[key] = TEST_VOLUME2[key]
model_update = self.driver.update_migrated_volume(self.context,
volume_info,
volume_info2,
TEST_VOLUME,
TEST_VOLUME2,
'available')
FAKE_MIGRATED_MODEL_UPDATE = {
@ -1405,6 +1401,10 @@ class FJISCSIDriverTestCase(test.TestCase):
'target_iqns': ISCSI_TARGET_IQN,
'target_lun': 0}
def volume_update(self, volume, diction):
for key, value in diction.items():
volume[key] = value
def test_get_volume_stats(self):
ret = self.driver.get_volume_stats(True)
@ -1412,9 +1412,11 @@ class FJISCSIDriverTestCase(test.TestCase):
def test_create_and_delete_volume(self):
model_info = self.driver.create_volume(TEST_VOLUME)
self.volume_update(TEST_VOLUME, model_info)
self.assertEqual(FAKE_MODEL_INFO1, model_info)
model_info = self.driver.create_volume(TEST_VOLUME2)
self.volume_update(TEST_VOLUME2, model_info)
self.assertEqual(FAKE_MODEL_INFO3, model_info)
self.driver.delete_volume(TEST_VOLUME)
@ -1428,6 +1430,7 @@ class FJISCSIDriverTestCase(test.TestCase):
'data': fake_mapdata}
model_info = self.driver.create_volume(TEST_VOLUME)
self.volume_update(TEST_VOLUME, model_info)
self.assertEqual(FAKE_MODEL_INFO1, model_info)
info = self.driver.initialize_connection(TEST_VOLUME,
@ -1447,9 +1450,11 @@ class FJISCSIDriverTestCase(test.TestCase):
def test_create_and_delete_snapshot(self):
model_info = self.driver.create_volume(TEST_VOLUME)
self.volume_update(TEST_VOLUME, model_info)
self.assertEqual(FAKE_MODEL_INFO1, model_info)
snap_info = self.driver.create_snapshot(TEST_SNAP)
self.volume_update(TEST_SNAP, snap_info)
self.assertEqual(FAKE_SNAP_INFO, snap_info)
self.driver.delete_snapshot(TEST_SNAP)
@ -1457,13 +1462,16 @@ class FJISCSIDriverTestCase(test.TestCase):
def test_create_volume_from_snapshot(self):
model_info = self.driver.create_volume(TEST_VOLUME)
self.volume_update(TEST_VOLUME, model_info)
self.assertEqual(FAKE_MODEL_INFO1, model_info)
snap_info = self.driver.create_snapshot(TEST_SNAP)
self.volume_update(TEST_SNAP, snap_info)
self.assertEqual(FAKE_SNAP_INFO, snap_info)
model_info = self.driver.create_volume_from_snapshot(TEST_CLONE,
TEST_SNAP)
self.volume_update(TEST_CLONE, model_info)
self.assertEqual(FAKE_MODEL_INFO2, model_info)
self.driver.delete_snapshot(TEST_SNAP)
@ -1472,9 +1480,11 @@ class FJISCSIDriverTestCase(test.TestCase):
def test_create_cloned_volume(self):
model_info = self.driver.create_volume(TEST_VOLUME)
self.volume_update(TEST_VOLUME, model_info)
self.assertEqual(FAKE_MODEL_INFO1, model_info)
model_info = self.driver.create_cloned_volume(TEST_CLONE, TEST_VOLUME)
self.volume_update(TEST_CLONE, model_info)
self.assertEqual(FAKE_MODEL_INFO2, model_info)
self.driver.delete_volume(TEST_CLONE)
@ -1485,60 +1495,34 @@ class FJISCSIDriverTestCase(test.TestCase):
# ThinProvisioningPool separately.
TEST_VOLUME_LIST = [TEST_VOLUME, TEST_VOLUME2]
FAKE_MODEL_INFO_LIST = [FAKE_MODEL_INFO1, FAKE_MODEL_INFO3]
model_info_list = []
for i in range(len(TEST_VOLUME_LIST)):
model_info = self.driver.create_volume(TEST_VOLUME_LIST[i])
self.volume_update(TEST_VOLUME_LIST[i], model_info)
self.assertEqual(FAKE_MODEL_INFO_LIST[i], model_info)
model_info_list.append(model_info)
for i in range(len(TEST_VOLUME_LIST)):
volume_info = {}
for key in TEST_VOLUME_LIST[i]:
if key == 'provider_location':
volume_info[key] = model_info_list[i][key]
elif key == 'metadata':
volume_info[key] = model_info_list[i][key]
else:
volume_info[key] = TEST_VOLUME_LIST[i][key]
self.driver.extend_volume(volume_info, 10)
self.driver.extend_volume(TEST_VOLUME_LIST[i], 10)
def test_create_volume_with_qos(self):
self.driver.common._get_qos_specs = mock.Mock()
self.driver.common._get_qos_specs.return_value = {'maxBWS': '700'}
self.driver.common._set_qos = mock.Mock()
model_info = self.driver.create_volume(TEST_VOLUME_QOS)
self.volume_update(TEST_VOLUME, model_info)
self.assertEqual(FAKE_MODEL_INFO_QOS, model_info)
self.driver.common._set_qos.assert_called()
def test_update_migrated_volume(self):
model_info = self.driver.create_volume(TEST_VOLUME)
self.volume_update(TEST_VOLUME, model_info)
self.assertEqual(FAKE_MODEL_INFO1, model_info)
volume_info = {}
for key in TEST_VOLUME:
if key == 'provider_location':
volume_info[key] = model_info[key]
elif key == 'metadata':
volume_info[key] = model_info[key]
else:
volume_info[key] = TEST_VOLUME[key]
model_info2 = self.driver.create_volume(TEST_VOLUME2)
self.volume_update(TEST_VOLUME2, model_info2)
self.assertEqual(FAKE_MODEL_INFO3, model_info2)
volume_info2 = {}
for key in TEST_VOLUME:
if key == 'provider_location':
volume_info2[key] = model_info2[key]
elif key == 'metadata':
volume_info2[key] = model_info2[key]
else:
volume_info2[key] = TEST_VOLUME2[key]
model_update = self.driver.update_migrated_volume(self.context,
volume_info,
volume_info2,
TEST_VOLUME,
TEST_VOLUME2,
'available')
FAKE_MIGRATED_MODEL_UPDATE = {
@ -1919,13 +1903,21 @@ class FJCommonTestCase(test.TestCase):
volume_no = self.driver.common._get_volume_number(vol_instance)
self.assertEqual(FAKE_LUN_NO1, volume_no)
def volume_update(self, volume, diction):
for key, value in diction.items():
volume[key] = value
def test_get_eternus_model(self):
ETERNUS_MODEL = self.driver.common._get_eternus_model()
self.assertEqual(3, ETERNUS_MODEL)
def test_get_matadata(self):
model_info = self.driver.create_volume(TEST_VOLUME)
self.volume_update(TEST_VOLUME, model_info)
self.assertEqual(FAKE_MODEL_INFO1, model_info)
TEST_METADATA = self.driver.common.get_metadata(TEST_VOLUME)
self.assertEqual({}, TEST_METADATA)
self.assertEqual(FAKE_LUN_META1, TEST_METADATA)
def test_is_qos_or_format_support(self):
QOS_SUPPORT = \
@ -2016,35 +2008,29 @@ class FJCommonTestCase(test.TestCase):
def test_update_migrated_volume(self):
model_info = self.driver.create_volume(TEST_VOLUME)
self.volume_update(TEST_VOLUME, model_info)
self.assertEqual(FAKE_MODEL_INFO1, model_info)
volume_info = {}
for key in TEST_VOLUME:
if key == 'provider_location':
volume_info[key] = model_info[key]
elif key == 'metadata':
volume_info[key] = model_info[key]
else:
volume_info[key] = TEST_VOLUME[key]
model_info2 = self.driver.create_volume(TEST_VOLUME2)
self.volume_update(TEST_VOLUME2, model_info2)
self.assertEqual(FAKE_MODEL_INFO3, model_info2)
volume_info2 = {}
for key in TEST_VOLUME:
if key == 'provider_location':
volume_info2[key] = model_info2[key]
elif key == 'metadata':
volume_info2[key] = model_info2[key]
else:
volume_info2[key] = TEST_VOLUME2[key]
model_update = self.driver.common.update_migrated_volume(self.context,
volume_info,
volume_info2)
TEST_VOLUME,
TEST_VOLUME2)
FAKE_MIGRATED_MODEL_UPDATE = {
'_name_id': TEST_VOLUME2['id'],
'provider_location': model_info2['provider_location']
}
self.assertEqual(FAKE_MIGRATED_MODEL_UPDATE, model_update)
def test_create_snapshot(self):
model_info = self.driver.create_volume(TEST_VOLUME)
self.volume_update(TEST_VOLUME, model_info)
self.assertEqual(FAKE_MODEL_INFO1, model_info)
snap_info = self.driver.common._create_snapshot(TEST_SNAP)
self.assertEqual(FAKE_SNAP_INFO, snap_info)
self.driver.delete_volume(TEST_VOLUME)

View File

@ -70,10 +70,11 @@ class FJDXCommon(object):
1.4.2 - Add the secondary check for copy-sessions when deleting volumes.
1.4.3 - Add fragment capacity information of RAID Group.
1.4.4 - Add support for update migrated volume.
1.4.5 - Add metadata for snapshot.
"""
VERSION = "1.4.4"
VERSION = "1.4.5"
stats = {
'driver_version': VERSION,
'storage_protocol': None,
@ -636,24 +637,18 @@ class FJDXCommon(object):
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
@lockutils.synchronized('ETERNUS-vol', 'cinder-', True)
def create_snapshot(self, snapshot):
"""Create snapshot using SnapOPC."""
LOG.debug('create_snapshot, '
'snapshot id: %(sid)s, volume id: %(vid)s.',
{'sid': snapshot['id'], 'vid': snapshot['volume_id']})
self.conn = self._get_eternus_connection()
snapshotname = snapshot['name']
volumename = snapshot['volume_name']
volume = snapshot['volume']
d_volumename = self._get_volume_name(snapshot, use_id=True)
s_volumename = self._get_volume_name(volume)
vol_instance = self._find_lun(volume)
repservice = self._find_eternus_service(CONSTANTS.REPL)
# Check the existence of volume.
if vol_instance is None:
if not vol_instance:
# Volume not found on ETERNUS.
msg = (_('create_snapshot, '
'volumename: %(s_volumename)s, '
@ -662,7 +657,37 @@ class FJDXCommon(object):
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
if repservice is None:
model_update = self._create_snapshot(snapshot)
return model_update
@lockutils.synchronized('ETERNUS-vol', 'cinder-', True)
def _create_snapshot(self, snapshot):
LOG.debug('create_snapshot, '
'snapshot id: %(sid)s, volume id: %(vid)s.',
{'sid': snapshot['id'], 'vid': snapshot['volume_id']})
self.conn = self._get_eternus_connection()
snapshotname = snapshot['name']
volume = snapshot['volume']
volumename = snapshot['volume_name']
d_volumename = self._get_volume_name(snapshot, use_id=True)
s_volumename = self._get_volume_name(volume)
vol_instance = self._find_lun(volume)
smis_service = self._find_eternus_service(CONSTANTS.REPL)
# Check the existence of volume.
if not vol_instance:
# Volume not found on ETERNUS.
msg = (_('create_snapshot, '
'volumename: %(s_volumename)s, '
'source volume not found on ETERNUS.')
% {'s_volumename': s_volumename})
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
if not smis_service:
msg = (_('create_snapshot, '
'volumename: %(volumename)s, '
'Replication Service not found.')
@ -674,7 +699,7 @@ class FJDXCommon(object):
eternus_pool = self._get_drvcfg('EternusSnapPool')
# Check the existence of pool
pool = self._find_pool(eternus_pool)
if pool is None:
if not pool:
msg = (_('create_snapshot, '
'eternus_pool: %(eternus_pool)s, '
'pool not found.')
@ -695,14 +720,26 @@ class FJDXCommon(object):
'd_volumename': d_volumename,
'pool': pool})
if self.model_name != CONSTANTS.DX_S2:
smis_method = 'CreateElementReplica'
params = {
'ElementName': d_volumename,
'TargetPool': pool,
'SyncType': self._pywbem_uint(7, '16'),
'SourceElement': vol_instance.path
}
else:
smis_method = 'CreateReplica'
params = {
'ElementName': d_volumename,
'TargetPool': pool,
'CopyType': self._pywbem_uint(4, '16'),
'SourceElement': vol_instance.path
}
# Invoke method for create snapshot
rc, errordesc, job = self._exec_eternus_service(
'CreateElementReplica',
repservice,
ElementName=d_volumename,
TargetPool=pool,
SyncType=self._pywbem_uint(7, '16'),
SourceElement=vol_instance.path)
smis_method, smis_service,
**params)
if rc != 0:
msg = (_('create_snapshot, '
@ -724,6 +761,7 @@ class FJDXCommon(object):
raise exception.VolumeBackendAPIException(data=msg)
else:
element = job['TargetElement']
d_volume_no = self._get_volume_number(element)
LOG.debug('create_snapshot, '
'volumename:%(volumename)s, '
@ -743,11 +781,17 @@ class FJDXCommon(object):
'vol_name': d_volumename,
}
sdv_no = self._get_volume_number(element)
metadata = {'FJ_SDV_Name': d_volumename,
'FJ_SDV_No': sdv_no,
'FJ_SDV_No': d_volume_no,
'FJ_Pool_Name': eternus_pool}
return (element_path, metadata)
d_metadata = self.get_metadata(snapshot)
d_metadata.update(metadata)
model_update = {
'provider_location': str(element_path),
'metadata': d_metadata,
}
return model_update
def delete_snapshot(self, snapshot):
"""Delete snapshot."""
@ -1197,7 +1241,7 @@ class FJDXCommon(object):
else:
ret = []
for e in elem.findall(".//" + tagname):
if (e.text is not None) and (e.text not in ret):
if e.text and (e.text not in ret):
ret.append(e.text)
if not ret:
@ -1250,8 +1294,7 @@ class FJDXCommon(object):
"""Get volume_name on ETERNUS from volume on OpenStack."""
LOG.debug('_get_volume_name, volume_id: %s.', volume['id'])
if (not use_id and 'provider_location' in volume and
volume['provider_location']):
if not use_id and volume['provider_location']:
location = eval(volume['provider_location'])
if 'vol_name' in location:
LOG.debug('_get_volume_name, by provider_location, '
@ -1609,7 +1652,7 @@ class FJDXCommon(object):
@lockutils.synchronized('ETERNUS-SMIS-getinstance', 'cinder-', True)
@utils.retry(exception.VolumeBackendAPIException)
def _get_eternus_instance(self, classname, allownone=False, **param_dict):
def _get_eternus_instance(self, classname, AllowNone=False, **param_dict):
"""Get Instance."""
LOG.debug('_get_eternus_instance, '
'classname: %(cls)s, param: %(param)s.',
@ -1619,7 +1662,7 @@ class FJDXCommon(object):
try:
ret = self.conn.GetInstance(classname, **param_dict)
except Exception as e:
if e.args[0] == 6 and allownone:
if e.args[0] == 6 and AllowNone:
return ret
else:
msg = _('_get_eternus_instance, Error:%s.') % e
@ -1703,6 +1746,7 @@ class FJDXCommon(object):
location = eval(volume['provider_location'])
classname = location['classname']
bindings = location['keybindings']
isSuccess = True
if classname and bindings:
LOG.debug('_find_lun, '
@ -1718,17 +1762,17 @@ class FJDXCommon(object):
{'volume_instance_name': volume_instance_name})
vol_instance = self._get_eternus_instance(volume_instance_name,
allownone=True,)
AllowNone=True)
if vol_instance and vol_instance['ElementName'] == volumename:
volumeinstance = vol_instance
except Exception:
volumeinstance = None
isSuccess = False
LOG.debug('_find_lun, '
'Cannot get volume instance from provider location, '
'Search all volume using EnumerateInstanceNames.')
if not volumeinstance:
if not isSuccess and self.model_name == CONSTANTS.DX_S2:
# For old version.
LOG.debug('_find_lun, '
'volumename: %(volumename)s.',

View File

@ -97,9 +97,15 @@ class FJDXFCDriver(driver.FibreChannelDriver):
def create_snapshot(self, snapshot):
"""Creates a snapshot."""
location, metadata = self.common.create_snapshot(snapshot)
LOG.debug('create_snapshot, '
'snap id: %(sid)s, volume id: %(vid)s, Enter method.',
{'sid': snapshot['id'], 'vid': snapshot['volume_id']})
return {'provider_location': str(location)}
model_update = self.common.create_snapshot(snapshot)
LOG.debug('create_snapshot, info: %s, Exit method.',
model_update['metadata'])
return model_update
def delete_snapshot(self, snapshot):
"""Deletes a snapshot."""

View File

@ -104,9 +104,15 @@ class FJDXISCSIDriver(driver.ISCSIDriver):
def create_snapshot(self, snapshot):
"""Creates a snapshot."""
element_path, metadata = self.common.create_snapshot(snapshot)
LOG.debug('create_snapshot, '
'snap id: %(sid)s, volume id: %(vid)s, Enter method.',
{'sid': snapshot['id'], 'vid': snapshot['volume_id']})
return {'provider_location': str(element_path)}
model_update = self.common.create_snapshot(snapshot)
LOG.debug('create_snapshot, info: %s, Exit method.',
model_update['metadata'])
return model_update
def delete_snapshot(self, snapshot):
"""Deletes a snapshot."""

View File

@ -0,0 +1,13 @@
---
features:
- |
Fujitsu ETERNUS DX driver: Add metadata to snapshot
After the snapshot is created, upload the information of the snapshot on
the storage to the metadata.
The metadata has the following information:
- ``FJ_SDV_Name``
- ``FJ_SDV_No``
- ``FJ_Pool_Name``