Fujitsu Driver: Support for update migrated volume

After migrated volume is completed, cinder invokes function
'update_migrated_volume'.

It updates provider_location, which possesses the new volume ID,
to match the provider_location of original volume.

Change-Id: I1fe29d077a657963016a581b6c87642a62979653
This commit is contained in:
inori
2023-11-16 21:27:35 -05:00
committed by xuq.fnstxz
parent a94e332818
commit 82d9b3f669
6 changed files with 248 additions and 4 deletions

View File

@@ -19,6 +19,7 @@ from unittest import mock
from oslo_utils import units
from cinder import context
from cinder import exception
from cinder import ssh_utils
from cinder.tests.unit import test
@@ -178,7 +179,7 @@ FAKE_POOLS = [{
}]
FAKE_STATS = {
'driver_version': '1.4.3',
'driver_version': '1.4.4',
'storage_protocol': 'iSCSI',
'vendor_name': 'FUJITSU',
'QoS_support': True,
@@ -188,7 +189,7 @@ FAKE_STATS = {
'pools': FAKE_POOLS,
}
FAKE_STATS2 = {
'driver_version': '1.4.3',
'driver_version': '1.4.4',
'storage_protocol': 'FC',
'vendor_name': 'FUJITSU',
'QoS_support': True,
@@ -198,7 +199,6 @@ FAKE_STATS2 = {
'pools': FAKE_POOLS,
}
# Volume1 in pool abcd1234_TPP
FAKE_KEYBIND1 = {
'SystemName': STORAGE_SYSTEM,
@@ -1007,6 +1007,8 @@ class FJFCDriverTestCase(test.TestCase):
driver = dx_fc.FJDXFCDriver(configuration=self.configuration)
self.driver = driver
self.context = context.get_admin_context()
def fake_exec_cli_with_eternus(self, exec_cmdline):
if exec_cmdline == "show users":
ret = ('\r\nCLI> %s\r\n00\r\n'
@@ -1219,6 +1221,42 @@ class FJFCDriverTestCase(test.TestCase):
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.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.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,
'available')
FAKE_MIGRATED_MODEL_UPDATE = {
'_name_id': TEST_VOLUME2['id'],
'provider_location': model_info2['provider_location']
}
self.assertEqual(FAKE_MIGRATED_MODEL_UPDATE, model_update)
class FJISCSIDriverTestCase(test.TestCase):
def __init__(self, *args, **kwargs):
@@ -1260,6 +1298,8 @@ class FJISCSIDriverTestCase(test.TestCase):
driver = dx_iscsi.FJDXISCSIDriver(configuration=self.configuration)
self.driver = driver
self.context = context.get_admin_context()
def fake_exec_cli_with_eternus(self, exec_cmdline):
if exec_cmdline == "show users":
ret = ('\r\nCLI> %s\r\n00\r\n'
@@ -1471,6 +1511,42 @@ class FJISCSIDriverTestCase(test.TestCase):
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.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.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,
'available')
FAKE_MIGRATED_MODEL_UPDATE = {
'_name_id': TEST_VOLUME2['id'],
'provider_location': model_info2['provider_location']
}
self.assertEqual(FAKE_MIGRATED_MODEL_UPDATE, model_update)
class FJCLITestCase(test.TestCase):
def __init__(self, *args, **kwargs):
@@ -1765,6 +1841,8 @@ class FJCommonTestCase(test.TestCase):
driver = dx_iscsi.FJDXISCSIDriver(configuration=self.configuration)
self.driver = driver
self.context = context.get_admin_context()
def fake_exec_cli_with_eternus(self, exec_cmdline):
if exec_cmdline == "show users":
ret = ('\r\nCLI> %s\r\n00\r\n'
@@ -1935,3 +2013,38 @@ class FJCommonTestCase(test.TestCase):
}]
copy_session_list = self.driver.common._get_copy_sessions_list()
self.assertEqual(FAKE_COPY_SESSION, copy_session_list)
def test_update_migrated_volume(self):
model_info = self.driver.create_volume(TEST_VOLUME)
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.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)
FAKE_MIGRATED_MODEL_UPDATE = {
'_name_id': TEST_VOLUME2['id'],
'provider_location': model_info2['provider_location']
}
self.assertEqual(FAKE_MIGRATED_MODEL_UPDATE, model_update)

View File

@@ -69,10 +69,11 @@ class FJDXCommon(object):
1.4.1 - Add the method for expanding RAID volumes by CLI.
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.
"""
VERSION = "1.4.3"
VERSION = "1.4.4"
stats = {
'driver_version': VERSION,
'storage_protocol': None,
@@ -2595,6 +2596,34 @@ class FJDXCommon(object):
{'poolname': poolname, 'target_pool': target_pool})
return poolname, target_pool
def update_migrated_volume(self, ctxt, volume, new_volume):
"""Update migrated volume."""
LOG.debug('update_migrated_volume, '
'source volume id: %(s_id)s, '
'target volume id: %(t_id)s.',
{'s_id': volume['id'], 't_id': new_volume['id']})
model_update = None
dst_metadata = self.get_metadata(new_volume)
src_metadata = self.get_metadata(volume)
LOG.debug('source: (%(src_meta)s)(%(src_loc)s), '
'target: (%(dst_meta)s)(%(dst_loc)s).',
{'src_meta': src_metadata,
'src_loc': volume['provider_location'],
'dst_meta': dst_metadata,
'dst_loc': new_volume['provider_location']})
if volume['provider_location']:
dst_location = new_volume['provider_location']
model_update = {'_name_id': new_volume['id'],
'provider_location': dst_location}
LOG.debug('update_migrated_volume, model_update: %s.',
model_update)
return model_update
def _get_eternus_model(self):
"""Get ENTERNUS model."""
self.conn = self._get_eternus_connection()

View File

@@ -173,6 +173,22 @@ class FJDXFCDriver(driver.FibreChannelDriver):
LOG.debug('extend_volume, '
'used pool name: %s, Exit method.', used_pool_name)
def update_migrated_volume(self, ctxt, volume, new_volume,
original_volume_status):
"""Update migrated volume."""
LOG.debug('update_migrated_volume, '
'source volume id: %(s_id)s, '
'target volume id: %(t_id)s, Enter method.',
{'s_id': volume['id'], 't_id': new_volume['id']})
model_update = self.common.update_migrated_volume(
ctxt, volume, new_volume)
LOG.debug('update_migrated_volume, '
'target volume meta: %s, Exit method.', model_update)
return model_update
def _get_metadata(self, volume):
v_metadata = volume.get('volume_metadata')
if v_metadata:

View File

@@ -159,3 +159,19 @@ class FJDXISCSIDriver(driver.ISCSIDriver):
LOG.debug('extend_volume, '
'used pool name: %s, Exit method.', used_pool_name)
def update_migrated_volume(self, ctxt, volume, new_volume,
original_volume_status):
"""Update migrated volume."""
LOG.debug('update_migrated_volume, '
'source volume id: %(s_id)s, '
'target volume id: %(t_id)s, Enter method.',
{'s_id': volume['id'], 't_id': new_volume['id']})
model_update = self.common.update_migrated_volume(
ctxt, volume, new_volume)
LOG.debug('update_migrated_volume, '
'target volume meta: %s, Exit method.', model_update)
return model_update

View File

@@ -46,6 +46,7 @@ Supported operations
* Clone a volume.
* Extend a volume.
* Get volume statistics.
* Migrate Volume.
Preparation
~~~~~~~~~~~
@@ -241,6 +242,65 @@ Configuration example
and the type ``DX_ISCSI`` is associated with the ``ISCSI``.
Supported Functions of the ETERNUS OpenStack VolumeDriver
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Migrate Volume
--------------
Moves volumes to a different storage pool.
#. ETERNUS AF/DX functions
* Creates migration destination volumes / deletes migration
source volumes.
* Sets access paths to migration volumes / deletes migration
access paths to migration source volumes.
* Uses Create Volume, Delete Volume, Attach Volume and Detach
Volume.
#. Cinder operation
* Copies data in the migration source volume to the migration
destination volume.
.. note::
Host information must be specified in Migrated Volume.
The input format is as follows:
``Host-Name@Backend-Name#Pool-Name``
For the following environment or settings, specify
``test.localhost@Backend1#PoolA`` for the host.
* PoolA is a pool specified in ``/etc/cinder/cinder_fujitsu_eternus_dx.xml``.
.. code-block:: console
$ hostname
test.localhost
$ cat /etc/cinder/cinder.conf
(snip)
[Backend1]
volume_driver=cinder.volume.drivers.fujitsu.eternus_dx.eternus_dx_fc.FJDXFCDriver
cinder_eternus_config_file = /etc/cinder/cinder_fujitsu_eternus_dx.xml
volume_backend_name=volume_backend_name1
.. warning::
There are some restrictions for volume migration:
#. You cannot migrate a volume that has snapshots.
#. You cannot use driver-assisted migration to move a volume to or from a
backend that does not use the ETERNUS OpenStack volume driver.
Supplementary Information for the Supported Functions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@@ -0,0 +1,10 @@
---
features:
- |
Fujitsu ETERNUS DX driver: Added support for update migrated volume
Now we update the required values to successfully complete the migration.
See the `Fujitsu ETERNUS DX driver documentation
<https://docs.openstack.org/cinder/latest/configuration/block-storage/drivers/fujitsu-eternus-dx-driver.html>`_
for details.