From 2d6ac671f2a47ed06d8eb288b86760ffccfd1e52 Mon Sep 17 00:00:00 2001 From: zengyingzhe Date: Tue, 20 Jun 2017 20:41:29 +0800 Subject: [PATCH] Change Huawei driver's private data storing place This patch is to fix issues at two circumstances: 1. Create volume from image by non-admin user, this operation will fail because Huawei driver tries to record LUN WWN at admin metadata, however non-admin user doesn't have the admin metadata access right, so exception is raised. 2. Restore volume backup to 3rd volume, this operation will also restore backup volume's metadata to the 3rd volume, but the data recorded in metadata is strong correlative to the corresponding LUN at backend storage, so this will break the one-to-one relationship between the restored volume and the LUN at storage. To fix the issues above, we moved all LUN private data to provider_location, stored as a dict string, not use admin metadata or metadata to store LUN private data. Change-Id: Id18622935ecaa1715491b4ede48c7b627e43d3fa Closes-Bug: #1699109 --- .../drivers/huawei/test_huawei_drivers.py | 311 ++++++++++++------ cinder/volume/drivers/huawei/huawei_driver.py | 91 +++-- cinder/volume/drivers/huawei/huawei_utils.py | 35 ++ cinder/volume/drivers/huawei/hypermetro.py | 8 +- cinder/volume/drivers/huawei/replication.py | 42 +-- cinder/volume/drivers/huawei/rest_client.py | 5 +- 6 files changed, 340 insertions(+), 152 deletions(-) diff --git a/cinder/tests/unit/volume/drivers/huawei/test_huawei_drivers.py b/cinder/tests/unit/volume/drivers/huawei/test_huawei_drivers.py index 41524facf48..2484b4cbb44 100644 --- a/cinder/tests/unit/volume/drivers/huawei/test_huawei_drivers.py +++ b/cinder/tests/unit/volume/drivers/huawei/test_huawei_drivers.py @@ -21,7 +21,6 @@ import mock import re import requests import tempfile -import unittest from xml.dom import minidom from xml.etree import ElementTree @@ -53,15 +52,25 @@ admin_contex = context.get_admin_context() vol_attrs = ('id', 'lun_type', 'provider_location', 'metadata') Volume = collections.namedtuple('Volume', vol_attrs) -PROVIDER_LOCATION = '11' +PROVIDER_LOCATION = ('{"huawei_lun_id": "11", ' + '"huawei_lun_wwn": "6643e8c1004c5f6723e9f454003"}') +PROVIDER_LOCATION_WITH_HYPERMETRO = ( + '{"huawei_lun_id": "11", ' + '"huawei_lun_wwn": "6643e8c1004c5f6723e9f454003", ' + '"hypermetro_id": "11", ' + '"remote_lun_id": "1"}') +SNAP_PROVIDER_LOCATION = '{"huawei_snapshot_id": "11"}' + HOST = 'ubuntu001@backend001#OpenStack_Pool' ID = '21ec7341-9256-497b-97d9-ef48edcf0635' ENCODE_NAME = huawei_utils.encode_name(ID) -ADMIN_METADATA = {'huawei_lun_wwn': '6643e8c1004c5f6723e9f454003'} +METADATA = {} TEST_PAIR_ID = "3400a30d844d0004" -REPLICA_DRIVER_DATA = '{"pair_id": "%s", "rmt_lun_id": "1"}' % TEST_PAIR_ID VOL_METADATA = [{'key': 'hypermetro_id', 'value': '11'}, {'key': 'remote_lun_id', 'value': '1'}] +ADMIN_METADATA = [{'key': 'huawei_lun_wwn', 'value': 'FAKE_WWN'}] +REPLICA_DRIVER_DATA = ('{"pair_id": "%s", "rmt_lun_id": "1", ' + '"rmt_lun_wwn": "FAKE_RMT_LUN_WWN"}') % TEST_PAIR_ID hypermetro_devices = """{ "remote_device": { @@ -502,7 +511,7 @@ FAKE_SNAPSHOT_LIST_INFO_RESPONSE = { "description": "0" }, "data": [{ - "ID": 11, + "ID": "11", "NAME": ENCODE_NAME }, ] } @@ -515,7 +524,7 @@ FAKE_CREATE_SNAPSHOT_INFO_RESPONSE = """ "code": 0 }, "data": { - "ID": 11, + "ID": "11", "NAME": "YheUoRwbSX2BxN7" } } @@ -529,7 +538,7 @@ FAKE_GET_SNAPSHOT_INFO_RESPONSE = """ "description": "0" }, "data": { - "ID": 11, + "ID": "11", "NAME": "YheUoRwbSX2BxN7" } } @@ -2231,21 +2240,22 @@ class HuaweiTestBase(test.TestCase): self.volume = fake_volume.fake_volume_obj( admin_contex, host=HOST, provider_location=PROVIDER_LOCATION, - admin_metadata=ADMIN_METADATA, id=ID) + metadata=METADATA, id=ID) self.snapshot = fake_snapshot.fake_snapshot_obj( - admin_contex, provider_location=PROVIDER_LOCATION, id=ID) + admin_contex, provider_location=SNAP_PROVIDER_LOCATION, id=ID) self.snapshot.volume = self.volume self.replica_volume = fake_volume.fake_volume_obj( admin_contex, host=HOST, provider_location=PROVIDER_LOCATION, - admin_metadata=ADMIN_METADATA, replication_status='disabled', + metadata=METADATA, replication_status='disabled', replication_driver_data=REPLICA_DRIVER_DATA, id=ID) self.hyper_volume = fake_volume.fake_volume_obj( - admin_contex, host=HOST, provider_location=PROVIDER_LOCATION, - volume_metadata=VOL_METADATA, id=ID) + admin_contex, host=HOST, + provider_location=PROVIDER_LOCATION_WITH_HYPERMETRO, + id=ID) self.original_volume = fake_volume.fake_volume_obj(admin_contex, id=ID) @@ -2271,12 +2281,14 @@ class HuaweiTestBase(test.TestCase): @mock.patch.object(rest_client, 'RestClient') def test_create_snapshot_success(self, mock_client): lun_info = self.driver.create_snapshot(self.snapshot) - self.assertEqual(11, lun_info['provider_location']) + self.assertDictEqual({"huawei_snapshot_id": "11"}, + json.loads(lun_info['provider_location'])) self.snapshot.volume_id = ID self.snapshot.volume = self.volume lun_info = self.driver.create_snapshot(self.snapshot) - self.assertEqual(11, lun_info['provider_location']) + self.assertDictEqual({"huawei_snapshot_id": "11"}, + json.loads(lun_info['provider_location'])) @ddt.data('1', '', '0') def test_copy_volume(self, input_speed): @@ -2328,6 +2340,75 @@ class HuaweiTestBase(test.TestCase): 'POST' ) + @ddt.data( + { + 'volume': fake_volume.fake_volume_obj( + admin_contex, + provider_location=PROVIDER_LOCATION), + 'expect': {'huawei_lun_id': '11', + 'huawei_lun_wwn': '6643e8c1004c5f6723e9f454003'} + }, + { + 'volume': fake_volume.fake_volume_obj( + admin_contex, + provider_location=None), + 'expect': {} + }, + { + 'volume': fake_volume.fake_volume_obj( + admin_contex, + provider_location=''), + 'expect': {} + }, + { + 'volume': fake_volume.fake_volume_obj( + admin_contex, + provider_location='11', + volume_admin_metadata=ADMIN_METADATA, + volume_metadata=VOL_METADATA + ), + 'expect': {'huawei_lun_id': '11', + 'huawei_lun_wwn': 'FAKE_WWN', + 'hypermetro_id': '11', + 'remote_lun_id': '1'} + } + ) + @ddt.unpack + def test_get_lun_metadata(self, volume, expect): + metadata = huawei_utils.get_lun_metadata(volume) + self.assertEqual(expect, metadata) + + @ddt.data( + { + 'snapshot': fake_snapshot.fake_snapshot_obj( + admin_contex, + provider_location=SNAP_PROVIDER_LOCATION), + 'expect': {'huawei_snapshot_id': '11'} + }, + { + 'snapshot': fake_snapshot.fake_snapshot_obj( + admin_contex, + provider_location=None), + 'expect': {} + }, + { + 'snapshot': fake_snapshot.fake_snapshot_obj( + admin_contex, + provider_location=''), + 'expect': {} + }, + { + 'snapshot': fake_snapshot.fake_snapshot_obj( + admin_contex, + provider_location='11'), + 'expect': {'huawei_snapshot_id': '11'} + } + ) + @ddt.unpack + def test_get_snapshot_metadata(self, snapshot, expect): + metadata = huawei_utils.get_snapshot_metadata(snapshot) + self.assertEqual(expect, metadata) + @ddt.ddt class HuaweiISCSIDriverTestCase(HuaweiTestBase): @@ -2411,12 +2492,18 @@ class HuaweiISCSIDriverTestCase(HuaweiTestBase): self.volume.host = 'ubuntu001@backend001#OpenStack_Pool' lun_info = self.driver.create_volume(self.volume) - self.assertEqual('1', lun_info['provider_location']) + expect_value = {"huawei_lun_id": "1", + "huawei_lun_wwn": "6643e8c1004c5f6723e9f454003"} + self.assertDictEqual(expect_value, + json.loads(lun_info['provider_location'])) # No pool info in the volume. self.volume.host = 'ubuntu001@backend001' lun_info = self.driver.create_volume(self.volume) - self.assertEqual('1', lun_info['provider_location']) + expect_value = {"huawei_lun_id": "1", + "huawei_lun_wwn": "6643e8c1004c5f6723e9f454003"} + self.assertDictEqual(expect_value, + json.loads(lun_info['provider_location'])) @ddt.data(FAKE_POOLS_UNSUPPORT_REPORT, FAKE_POOLS_SUPPORT_REPORT) def test_delete_replication_fail(self, pool_data): @@ -2609,7 +2696,6 @@ class HuaweiISCSIDriverTestCase(HuaweiTestBase): def test_delete_snapshot_success(self): self.driver.delete_snapshot(self.snapshot) - @unittest.skip("Skip until bug #1578986 is fixed") def test_create_volume_from_snapsuccess(self): self.mock_object( huawei_driver.HuaweiBaseDriver, @@ -2617,13 +2703,17 @@ class HuaweiISCSIDriverTestCase(HuaweiTestBase): return_value={'extra_specs': sync_replica_specs}) self.mock_object(replication.ReplicaCommonDriver, 'sync') model_update = self.driver.create_volume_from_snapshot(self.volume, - self.volume) - self.assertEqual('1', model_update['provider_location']) + self.snapshot) + expect_value = {"huawei_lun_id": "1", + "huawei_lun_wwn": "6643e8c1004c5f6723e9f454003"} + self.assertDictEqual(expect_value, + json.loads(model_update['provider_location'])) driver_data = {'pair_id': TEST_PAIR_ID, - 'rmt_lun_id': '1'} - driver_data = replication.to_string(driver_data) - self.assertEqual(driver_data, model_update['replication_driver_data']) + 'rmt_lun_id': '1', + 'rmt_lun_wwn': '6643e8c1004c5f6723e9f454003'} + self.assertDictEqual( + driver_data, json.loads(model_update['replication_driver_data'])) self.assertEqual('available', model_update['replication_status']) @mock.patch.object(huawei_driver.HuaweiISCSIDriver, @@ -2810,19 +2900,19 @@ class HuaweiISCSIDriverTestCase(HuaweiTestBase): self.driver.extend_volume, self.volume, 3) - def test_get_admin_metadata(self): + def test_get_volume_metadata(self): metadata = [{'key': 'huawei_lun_wwn', 'value': '1'}] tmp_volume = fake_volume.fake_volume_obj( - admin_contex, volume_admin_metadata=metadata) + admin_contex, volume_metadata=metadata) expected_value = {'huawei_lun_wwn': '1'} - admin_metadata = huawei_utils.get_admin_metadata(tmp_volume) - self.assertEqual(expected_value, admin_metadata) + metadata = huawei_utils.get_volume_metadata(tmp_volume) + self.assertEqual(expected_value, metadata) - metadata = {'huawei_lun_wwn': '1'} + expected_value = {'huawei_lun_wwn': '1'} tmp_volume = fake_volume.fake_volume_obj(admin_contex) - tmp_volume.admin_metadata = metadata - admin_metadata = huawei_utils.get_admin_metadata(tmp_volume) - self.assertEqual(expected_value, admin_metadata) + tmp_volume.metadata = expected_value + metadata = huawei_utils.get_volume_metadata(tmp_volume) + self.assertEqual(expected_value, metadata) def test_login_fail(self): self.driver.client.test_fail = True @@ -2972,7 +3062,10 @@ class HuaweiISCSIDriverTestCase(HuaweiTestBase): def test_create_smartqos(self, mock_qos_value, pool_data): self.driver.support_func = pool_data lun_info = self.driver.create_volume(self.volume) - self.assertEqual('1', lun_info['provider_location']) + expect_value = {"huawei_lun_id": "1", + "huawei_lun_wwn": "6643e8c1004c5f6723e9f454003"} + self.assertDictEqual(expect_value, + json.loads(lun_info['provider_location'])) @ddt.data('front-end', 'back-end') @mock.patch.object(huawei_driver.HuaweiBaseDriver, '_get_volume_params', @@ -2996,7 +3089,10 @@ class HuaweiISCSIDriverTestCase(HuaweiTestBase): 'consumer': mock_consumer}) self.driver.support_func = FAKE_POOLS_SUPPORT_REPORT lun_info = self.driver.create_volume(self.volume) - self.assertEqual('1', lun_info['provider_location']) + expect_value = {"huawei_lun_id": "1", + "huawei_lun_wwn": "6643e8c1004c5f6723e9f454003"} + self.assertDictEqual(expect_value, + json.loads(lun_info['provider_location'])) @ddt.data([{'specs': {'maxBandWidth': '100', 'IOType': '3'}}, FAKE_POOLS_UNSUPPORT_REPORT], @@ -3062,7 +3158,10 @@ class HuaweiISCSIDriverTestCase(HuaweiTestBase): mock_array_version): self.driver.support_func = FAKE_POOLS_SUPPORT_REPORT lun_info = self.driver.create_volume(self.volume) - self.assertEqual('1', lun_info['provider_location']) + expect_value = {"huawei_lun_id": "1", + "huawei_lun_wwn": "6643e8c1004c5f6723e9f454003"} + self.assertDictEqual(expect_value, + json.loads(lun_info['provider_location'])) @mock.patch.object(smartx.SmartQos, 'get_qos_by_volume_type', return_value={'MINIOPS': '100', @@ -3077,7 +3176,10 @@ class HuaweiISCSIDriverTestCase(HuaweiTestBase): mock_array_version): self.driver.support_func = FAKE_POOLS_SUPPORT_REPORT lun_info = self.driver.create_volume(self.volume) - self.assertEqual('1', lun_info['provider_location']) + expect_value = {"huawei_lun_id": "1", + "huawei_lun_wwn": "6643e8c1004c5f6723e9f454003"} + self.assertDictEqual(expect_value, + json.loads(lun_info['provider_location'])) @mock.patch.object(smartx.SmartQos, 'get_qos_by_volume_type', return_value={'MINIOPS': '100', @@ -3165,7 +3267,10 @@ class HuaweiISCSIDriverTestCase(HuaweiTestBase): 'partitionname': 'partition-test'}) def test_create_smartx(self, mock_volume_types, mock_add_lun_to_partition): lun_info = self.driver.create_volume(self.volume) - self.assertEqual('1', lun_info['provider_location']) + expect_value = {"huawei_lun_id": "1", + "huawei_lun_wwn": "6643e8c1004c5f6723e9f454003"} + self.assertDictEqual(expect_value, + json.loads(lun_info['provider_location'])) @ddt.data([{'smarttier': 'true', 'smartcache': 'true', 'smartpartition': 'true', @@ -3308,10 +3413,13 @@ class HuaweiISCSIDriverTestCase(HuaweiTestBase): mock_pool_info, mock_all_pool_info, mock_login_return): - metadata = {"hypermetro_id": '11', - "remote_lun_id": '1'} + location = {"huawei_lun_id": "1", + "hypermetro_id": "11", + "remote_lun_id": "1", + "huawei_lun_wwn": "6643e8c1004c5f6723e9f454003"} lun_info = self.driver.create_volume(self.hyper_volume) - self.assertEqual(metadata, lun_info['metadata']) + self.assertDictEqual(location, + json.loads(lun_info['provider_location'])) @ddt.data(FAKE_POOLS_UNSUPPORT_REPORT, FAKE_POOLS_SUPPORT_REPORT) @mock.patch.object(huawei_driver.HuaweiBaseDriver, '_get_volume_params', @@ -3552,12 +3660,10 @@ class HuaweiISCSIDriverTestCase(HuaweiTestBase): external_ref = {'source-name': 'LUN1'} model_update = self.driver.manage_existing(self.volume, external_ref) - expected_val = { - 'admin_metadata': { - 'huawei_lun_wwn': '6643e8c1004c5f6723e9f454003' - }, - 'provider_location': 'ID1'} - self.assertEqual(expected_val, model_update) + location = {"huawei_lun_wwn": "6643e8c1004c5f6723e9f454003", + "huawei_lun_id": "ID1"} + self.assertDictEqual(location, + json.loads(model_update['provider_location'])) @ddt.data([[{'PRILUNID': 'ID1'}], []], [[{'PRILUNID': 'ID2'}], ['ID1', 'ID2']]) @@ -3653,12 +3759,10 @@ class HuaweiISCSIDriverTestCase(HuaweiTestBase): self.driver.support_func = pool_data model_update = self.driver.manage_existing(self.volume, external_ref) - expected_val = { - 'admin_metadata': { - 'huawei_lun_wwn': '6643e8c1004c5f6723e9f454003' - }, - 'provider_location': 'ID1'} - self.assertEqual(expected_val, model_update) + expected = {"huawei_lun_wwn": "6643e8c1004c5f6723e9f454003", + "huawei_lun_id": "ID1"} + self.assertDictEqual(expected, + json.loads(model_update['provider_location'])) def test_unmanage(self): self.driver.unmanage(self.volume) @@ -3708,12 +3812,14 @@ class HuaweiISCSIDriverTestCase(HuaweiTestBase): external_ref = {'source-name': 'test1'} model_update = self.driver.manage_existing_snapshot(self.snapshot, external_ref) - self.assertEqual({'provider_location': 'ID1'}, model_update) + expect_value = {'provider_location': '{"huawei_snapshot_id": "ID1"}'} + self.assertEqual(expect_value, model_update) external_ref = {'source-id': 'ID1'} model_update = self.driver.manage_existing_snapshot(self.snapshot, external_ref) - self.assertEqual({'provider_location': 'ID1'}, model_update) + expect_value = {'provider_location': '{"huawei_snapshot_id": "ID1"}'} + self.assertEqual(expect_value, model_update) @mock.patch.object(rest_client.RestClient, 'get_snapshot_info', return_value={'ID': 'ID1', @@ -3769,9 +3875,10 @@ class HuaweiISCSIDriverTestCase(HuaweiTestBase): model_update = self.driver.create_volume(self.replica_volume) driver_data = {'pair_id': TEST_PAIR_ID, - 'rmt_lun_id': '1'} - driver_data = replication.to_string(driver_data) - self.assertEqual(driver_data, model_update['replication_driver_data']) + 'rmt_lun_id': '1', + 'rmt_lun_wwn': '6643e8c1004c5f6723e9f454003'} + self.assertDictEqual( + driver_data, json.loads(model_update['replication_driver_data'])) self.assertEqual('available', model_update['replication_status']) @ddt.data( @@ -3888,7 +3995,6 @@ class HuaweiISCSIDriverTestCase(HuaweiTestBase): return_value=False) self.driver.delete_volume(self.replica_volume) - @unittest.skip("Skip until bug #1578986 is fixed") def test_wait_volume_online(self): replica = FakeReplicaPairManager(self.driver.client, self.driver.replica_client, @@ -3907,7 +4013,6 @@ class HuaweiISCSIDriverTestCase(HuaweiTestBase): self.driver.client, lun_info) - @unittest.skip("Skip until bug #1578986 is fixed") def test_wait_second_access(self): pair_id = '1' access_ro = constants.REPLICA_SECOND_RO @@ -3924,7 +4029,6 @@ class HuaweiISCSIDriverTestCase(HuaweiTestBase): self.assertRaises(exception.VolumeBackendAPIException, common_driver.wait_second_access, pair_id, access_rw) - @unittest.skip("Skip until bug #1578986 is fixed") def test_wait_replica_ready(self): normal_status = { 'RUNNINGSTATUS': constants.REPLICA_RUNNING_STATUS_NORMAL, @@ -4052,12 +4156,19 @@ class HuaweiISCSIDriverTestCase(HuaweiTestBase): v_id = volumes_update[0]['volume_id'] v_update = volumes_update[0]['updates'] self.assertEqual(self.replica_volume.id, v_id) - self.assertEqual('1', v_update['provider_location']) + + expect_location = {"huawei_lun_wwn": "FAKE_RMT_LUN_WWN", + "huawei_lun_id": "1"} + self.assertDictEqual( + expect_location, json.loads(v_update['provider_location'])) self.assertEqual('failed-over', v_update['replication_status']) + + metadata = huawei_utils.get_lun_metadata(self.replica_volume) new_drv_data = {'pair_id': TEST_PAIR_ID, - 'rmt_lun_id': self.replica_volume.provider_location} - new_drv_data = replication.to_string(new_drv_data) - self.assertEqual(new_drv_data, v_update['replication_driver_data']) + 'rmt_lun_id': metadata['huawei_lun_id'], + 'rmt_lun_wwn': metadata['huawei_lun_wwn']} + self.assertDictEqual( + new_drv_data, json.loads(v_update['replication_driver_data'])) @ddt.data({}, {'pair_id': TEST_PAIR_ID}) def test_failover_replica_volumes_invalid_drv_data(self, mock_drv_data): @@ -4110,12 +4221,19 @@ class HuaweiISCSIDriverTestCase(HuaweiTestBase): v_id = volumes_update[0]['volume_id'] v_update = volumes_update[0]['updates'] self.assertEqual(self.replica_volume.id, v_id) - self.assertEqual('1', v_update['provider_location']) + + expect_location = {"huawei_lun_wwn": "FAKE_RMT_LUN_WWN", + "huawei_lun_id": "1"} + self.assertDictEqual( + expect_location, json.loads(v_update['provider_location'])) self.assertEqual('available', v_update['replication_status']) + + metadata = huawei_utils.get_lun_metadata(self.replica_volume) new_drv_data = {'pair_id': TEST_PAIR_ID, - 'rmt_lun_id': self.replica_volume.provider_location} - new_drv_data = replication.to_string(new_drv_data) - self.assertEqual(new_drv_data, v_update['replication_driver_data']) + 'rmt_lun_id': metadata['huawei_lun_id'], + 'rmt_lun_wwn': metadata['huawei_lun_wwn']} + self.assertDictEqual( + new_drv_data, json.loads(v_update['replication_driver_data'])) @ddt.data({}, {'pair_id': TEST_PAIR_ID}) def test_failback_replica_volumes_invalid_drv_data(self, mock_drv_data): @@ -4145,7 +4263,6 @@ class HuaweiISCSIDriverTestCase(HuaweiTestBase): self.assertEqual(self.replica_volume.id, v_id) self.assertEqual('error', v_update['replication_status']) - @unittest.skip("Skip until bug #1578986 is fixed") @mock.patch('oslo_service.loopingcall.FixedIntervalLoopingCall', new=utils.ZeroIntervalLoopingCall) @mock.patch.object(replication.PairOp, 'is_primary', @@ -4201,7 +4318,6 @@ class HuaweiISCSIDriverTestCase(HuaweiTestBase): common_driver.protect_second(replica_id) common_driver.unprotect_second(replica_id) - @unittest.skip("Skip until bug #1578986 is fixed") def test_replication_driver_sync(self): replica_id = TEST_PAIR_ID op = replication.PairOp(self.driver.client) @@ -4312,11 +4428,12 @@ class HuaweiISCSIDriverTestCase(HuaweiTestBase): model, snapshots = ( self.driver.create_group_snapshot(ctxt, self.group_snapshot, test_snapshots)) - snapshots_model_update = [{'id': '21ec7341-9256-497b-97d9' - '-ef48edcf0635', - 'status': 'available', - 'provider_location': 11}] - self.assertEqual(snapshots_model_update, snapshots) + + self.assertEqual('21ec7341-9256-497b-97d9-ef48edcf0635', + snapshots[0]['id']) + self.assertEqual('available', snapshots[0]['status']) + self.assertDictEqual({'huawei_snapshot_id': '11'}, + json.loads(snapshots[0]['provider_location'])) self.assertEqual(fields.GroupSnapshotStatus.AVAILABLE, model['status']) @cg_or_cg_snapshot @@ -4380,7 +4497,10 @@ class HuaweiFCDriverTestCase(HuaweiTestBase): def test_create_volume_success(self): lun_info = self.driver.create_volume(self.volume) - self.assertEqual('1', lun_info['provider_location']) + expect_value = {"huawei_lun_id": "1", + "huawei_lun_wwn": "6643e8c1004c5f6723e9f454003"} + self.assertDictEqual(expect_value, + json.loads(lun_info['provider_location'])) @ddt.data(FAKE_POOLS_UNSUPPORT_REPORT, FAKE_POOLS_SUPPORT_REPORT) def test_delete_volume_success(self, pool_data): @@ -4390,11 +4510,13 @@ class HuaweiFCDriverTestCase(HuaweiTestBase): def test_delete_snapshot_success(self): self.driver.delete_snapshot(self.snapshot) - @unittest.skip("Skip until bug #1578986 is fixed") def test_create_volume_from_snapsuccess(self): lun_info = self.driver.create_volume_from_snapshot(self.volume, - self.volume) - self.assertEqual('1', lun_info['provider_location']) + self.snapshot) + expect_value = {"huawei_lun_id": "1", + "huawei_lun_wwn": "6643e8c1004c5f6723e9f454003"} + self.assertDictEqual(expect_value, + json.loads(lun_info['provider_location'])) @mock.patch.object(huawei_driver.HuaweiFCDriver, 'initialize_connection', @@ -4606,7 +4728,6 @@ class HuaweiFCDriverTestCase(HuaweiTestBase): '12') self.assertFalse(result) - @unittest.skip("Skip until bug #1578986 is fixed") @ddt.data(FAKE_POOLS_UNSUPPORT_REPORT, FAKE_POOLS_SUPPORT_REPORT) @mock.patch.object(rest_client, 'RestClient') def test_migrate_volume_success(self, mock_add_lun_to_partition, @@ -4688,13 +4809,15 @@ class HuaweiFCDriverTestCase(HuaweiTestBase): self.assertFalse(is_valid) # storage_protocol is not match current protocol and volume status is # 'in-use'. + location = ('{"huawei_lun_wwn": "6643e8c1004c5f6723e9f454003", ' + '"huawei_lun_id": "11"}') volume_in_use = {'name': 'volume-21ec7341-9256-497b-97d9-ef48edcf0635', 'size': 2, 'volume_name': 'vol1', 'id': ID, 'volume_id': '21ec7341-9256-497b-97d9-ef48edcf0635', 'volume_attachment': 'in-use', - 'provider_location': '11'} + 'provider_location': location} invalid_host2 = {'host': 'ubuntu001@backend002#OpenStack_Pool', 'capabilities': {'location_info': '210235G7J20000000001', @@ -4743,7 +4866,6 @@ class HuaweiFCDriverTestCase(HuaweiTestBase): test_new_type, None, test_host) self.assertTrue(retype) - @unittest.skip("Skip until bug #1578986 is fixed") @ddt.data(FAKE_POOLS_UNSUPPORT_REPORT, FAKE_POOLS_SUPPORT_REPORT) @mock.patch.object(rest_client, 'RestClient') @mock.patch.object( @@ -4934,7 +5056,10 @@ class HuaweiFCDriverTestCase(HuaweiTestBase): def test_multi_resturls_success(self): self.driver.client.test_multi_url_flag = True lun_info = self.driver.create_volume(self.volume) - self.assertEqual('1', lun_info['provider_location']) + expect_value = {"huawei_lun_id": "1", + "huawei_lun_wwn": "6643e8c1004c5f6723e9f454003"} + self.assertDictEqual(expect_value, + json.loads(lun_info['provider_location'])) def test_get_id_from_result(self): result = {} @@ -4998,10 +5123,13 @@ class HuaweiFCDriverTestCase(HuaweiTestBase): mock_volume_ready, mock_logout): - metadata = {"hypermetro_id": '11', - "remote_lun_id": '1'} + location = {"huawei_lun_id": "1", + "hypermetro_id": "11", + "remote_lun_id": "1", + "huawei_lun_wwn": "6643e8c1004c5f6723e9f454003"} lun_info = self.driver.create_volume(self.hyper_volume) - self.assertEqual(metadata, lun_info['metadata']) + self.assertDictEqual(location, + json.loads(lun_info['provider_location'])) @ddt.data(FAKE_POOLS_UNSUPPORT_REPORT, FAKE_POOLS_SUPPORT_REPORT) @mock.patch.object(huawei_driver.HuaweiBaseDriver, '_get_volume_params', @@ -5030,7 +5158,7 @@ class HuaweiFCDriverTestCase(HuaweiTestBase): self.assertRaises(exception.VolumeBackendAPIException, self.driver.metro.create_hypermetro, "11", {}) - @mock.patch.object(huawei_driver.huawei_utils, 'get_volume_metadata', + @mock.patch.object(huawei_driver.huawei_utils, 'get_lun_metadata', return_value={'hypermetro_id': '3400a30d844d0007', 'remote_lun_id': '1'}) @mock.patch.object(rest_client.RestClient, 'do_mapping', @@ -5044,13 +5172,13 @@ class HuaweiFCDriverTestCase(HuaweiTestBase): mock_map.assert_called_once_with('1', '0', '1', hypermetro_lun=True) - @mock.patch.object(huawei_driver.huawei_utils, 'get_volume_metadata', + @mock.patch.object(huawei_driver.huawei_utils, 'get_lun_metadata', return_value={'hypermetro_id': '3400a30d844d0007', 'remote_lun_id': '1'}) def test_terminate_hypermetro_connection_success(self, mock_metradata): self.driver.metro.disconnect_volume_fc(self.volume, FakeConnector) - @mock.patch.object(huawei_driver.huawei_utils, 'get_volume_metadata', + @mock.patch.object(huawei_driver.huawei_utils, 'get_lun_metadata', return_value={'hypermetro_id': '3400a30d844d0007', 'remote_lun_id': None}) @mock.patch.object(rest_client.RestClient, 'get_lun_id_by_name', @@ -5058,15 +5186,14 @@ class HuaweiFCDriverTestCase(HuaweiTestBase): def test_hypermetroid_none_fail(self, mock_metadata, moke_metro_name): self.assertRaises(exception.VolumeBackendAPIException, self.driver.metro.connect_volume_fc, - self.volume, + self.hyper_volume, FakeConnector) - @unittest.skip("Skip until bug #1578986 is fixed") def test_wait_volume_ready_success(self): flag = self.driver.metro._wait_volume_ready("11") self.assertIsNone(flag) - @mock.patch.object(huawei_driver.huawei_utils, 'get_volume_metadata', + @mock.patch.object(huawei_driver.huawei_utils, 'get_lun_metadata', return_value={'hypermetro_id': '3400a30d844d0007', 'remote_lun_id': '1'}) @mock.patch.object(rest_client.RestClient, 'get_online_free_wwns', @@ -5078,7 +5205,7 @@ class HuaweiFCDriverTestCase(HuaweiTestBase): mock_host_initiators): self.assertRaises(exception.VolumeBackendAPIException, self.driver.metro.connect_volume_fc, - self.volume, + self.hyper_volume, FakeConnector) def test_create_snapshot_fail_hypermetro(self): @@ -5198,7 +5325,7 @@ class HuaweiFCDriverTestCase(HuaweiTestBase): @mock.patch.object(huawei_driver.HuaweiBaseDriver, '_get_group_type', return_value=[{"hypermetro": "true"}]) - @mock.patch.object(huawei_driver.huawei_utils, 'get_volume_metadata', + @mock.patch.object(huawei_driver.huawei_utils, 'get_lun_metadata', return_value={'hypermetro_id': '3400a30d844d0007', 'remote_lun_id': '59'}) @cg_or_cg_snapshot diff --git a/cinder/volume/drivers/huawei/huawei_driver.py b/cinder/volume/drivers/huawei/huawei_driver.py index b04c0211d8f..0870bab5f39 100644 --- a/cinder/volume/drivers/huawei/huawei_driver.py +++ b/cinder/volume/drivers/huawei/huawei_driver.py @@ -344,17 +344,13 @@ class HuaweiBaseDriver(driver.VolumeDriver): {'volume': volume.id, 'params': params}) return params - def _create_volume(self, volume, lun_params): + def _create_volume(self, lun_params): # Create LUN on the array. - model_update = {} lun_info = self.client.create_lun(lun_params) - model_update['provider_location'] = lun_info['ID'] + metadata = {'huawei_lun_id': lun_info['ID'], + 'huawei_lun_wwn': lun_info['WWN']} + model_update = {'metadata': metadata} - admin_metadata = huawei_utils.get_admin_metadata(volume) - admin_metadata.update({'huawei_lun_wwn': lun_info['WWN']}) - model_update['admin_metadata'] = admin_metadata - metadata = huawei_utils.get_volume_metadata(volume) - model_update['metadata'] = metadata return lun_info, model_update def _create_base_type_volume(self, opts, volume, volume_type): @@ -363,7 +359,7 @@ class HuaweiBaseDriver(driver.VolumeDriver): Base type is the service type which doesn't conflict with the other. """ lun_params = self._get_lun_params(volume, opts) - lun_info, model_update = self._create_volume(volume, lun_params) + lun_info, model_update = self._create_volume(lun_params) lun_id = lun_info['ID'] try: @@ -438,10 +434,15 @@ class HuaweiBaseDriver(driver.VolumeDriver): model_update = self._add_extend_type_to_volume(opts, lun_params, lun_info, model_update) + + model_update['provider_location'] = huawei_utils.to_string( + **model_update.pop('metadata')) + return model_update def _delete_volume(self, volume): - lun_id = volume.provider_location + metadata = huawei_utils.get_lun_metadata(volume) + lun_id = metadata.get('huawei_lun_id') if not lun_id: return @@ -470,7 +471,7 @@ class HuaweiBaseDriver(driver.VolumeDriver): smart_qos = smartx.SmartQos(self.client) smart_qos.remove(qos_id, lun_id) - metadata = huawei_utils.get_volume_metadata(volume) + metadata = huawei_utils.get_lun_metadata(volume) if 'hypermetro_id' in metadata: metro = hypermetro.HuaweiHyperMetro(self.client, self.rmt_client, @@ -658,7 +659,9 @@ class HuaweiBaseDriver(driver.VolumeDriver): pool_info = self.client.get_pool_info(pool_name, pools) src_volume_name = huawei_utils.encode_name(volume.id) dst_volume_name = six.text_type(hash(src_volume_name)) - src_id = volume.provider_location + + metadata = huawei_utils.get_lun_metadata(volume) + src_id = metadata['huawei_lun_id'] opts = None qos = None @@ -678,9 +681,12 @@ class HuaweiBaseDriver(driver.VolumeDriver): lun_info = self.client.get_lun_info(src_id) - policy = lun_info['DATATRANSFERPOLICY'] if opts['policy']: policy = opts['policy'] + else: + policy = lun_info.get('DATATRANSFERPOLICY', + self.configuration.lun_policy) + lun_params = { 'NAME': dst_volume_name, 'PARENTID': pool_info['ID'], @@ -691,8 +697,12 @@ class HuaweiBaseDriver(driver.VolumeDriver): 'PREFETCHPOLICY': lun_info['PREFETCHPOLICY'], 'PREFETCHVALUE': lun_info['PREFETCHVALUE'], 'DATATRANSFERPOLICY': policy, - 'READCACHEPOLICY': lun_info['READCACHEPOLICY'], - 'WRITECACHEPOLICY': lun_info['WRITECACHEPOLICY'], + 'READCACHEPOLICY': lun_info.get( + 'READCACHEPOLICY', + self.configuration.lun_read_cache_policy), + 'WRITECACHEPOLICY': lun_info.get( + 'WRITECACHEPOLICY', + self.configuration.lun_write_cache_policy), 'OWNINGCONTROLLER': lun_info['OWNINGCONTROLLER'], } for item in lun_params.keys(): @@ -734,7 +744,8 @@ class HuaweiBaseDriver(driver.VolumeDriver): raise exception.VolumeBackendAPIException(data=err_msg) snapshotname = huawei_utils.encode_name(snapshot.id) - snapshot_id = snapshot.provider_location + metadata = huawei_utils.get_snapshot_metadata(snapshot) + snapshot_id = metadata.get('huawei_snapshot_id') if snapshot_id is None: snapshot_id = self.client.get_snapshot_id_by_name(snapshotname) if snapshot_id is None: @@ -748,7 +759,7 @@ class HuaweiBaseDriver(driver.VolumeDriver): lun_params, lun_info, model_update = ( self._create_base_type_volume(opts, volume, volume_type)) - tgt_lun_id = model_update['provider_location'] + tgt_lun_id = lun_info['ID'] luncopy_name = huawei_utils.encode_name(volume.id) LOG.info( 'create_volume_from_snapshot: src_lun_id: %(src_lun_id)s, ' @@ -778,6 +789,9 @@ class HuaweiBaseDriver(driver.VolumeDriver): # now, not hypermetro. model_update = self._add_extend_type_to_volume(opts, lun_params, lun_info, model_update) + model_update['provider_location'] = huawei_utils.to_string( + **model_update.pop('metadata')) + return model_update def create_cloned_volume(self, volume, src_vref): @@ -817,7 +831,8 @@ class HuaweiBaseDriver(driver.VolumeDriver): If not exists, raise or log warning. """ # Firstly, try to find LUN ID by volume.provider_location. - lun_id = volume.provider_location + metadata = huawei_utils.get_lun_metadata(volume) + lun_id = metadata.get('huawei_lun_id') # If LUN ID not recorded, find LUN ID by LUN NAME. if not lun_id: volume_name = huawei_utils.encode_name(volume.id) @@ -831,8 +846,7 @@ class HuaweiBaseDriver(driver.VolumeDriver): raise exception.VolumeBackendAPIException(data=msg) return - metadata = huawei_utils.get_admin_metadata(volume) - lun_wwn = metadata.get('huawei_lun_wwn') if metadata else None + lun_wwn = metadata.get('huawei_lun_wwn') if not lun_wwn: LOG.debug("No LUN WWN recorded for volume %s.", volume.id) @@ -908,7 +922,8 @@ class HuaweiBaseDriver(driver.VolumeDriver): snapshot_id = snapshot_info['ID'] self.client.activate_snapshot(snapshot_id) - return {'provider_location': snapshot_info['ID'], + location = huawei_utils.to_string(huawei_snapshot_id=snapshot_id) + return {'provider_location': location, 'lun_info': snapshot_info} def delete_snapshot(self, snapshot): @@ -921,7 +936,8 @@ class HuaweiBaseDriver(driver.VolumeDriver): {'snapshot': snapshotname, 'volume': volume_name},) - snapshot_id = snapshot.provider_location + metadata = huawei_utils.get_snapshot_metadata(snapshot) + snapshot_id = metadata.get('huawei_snapshot_id') if snapshot_id is None: snapshot_id = self.client.get_snapshot_id_by_name(snapshotname) @@ -1196,7 +1212,8 @@ class HuaweiBaseDriver(driver.VolumeDriver): 'replication_type': None, } - lun_id = volume.provider_location + metadata = huawei_utils.get_lun_metadata(volume) + lun_id = metadata['huawei_lun_id'] old_opts = self.get_lun_specs(lun_id) new_specs = new_type['extra_specs'] @@ -1476,12 +1493,10 @@ class HuaweiBaseDriver(driver.VolumeDriver): {'old_name': lun_info.get('NAME'), 'new_name': new_name}) self.client.rename_lun(lun_id, new_name, description) - metadata = huawei_utils.get_admin_metadata(volume) - metadata.update({'huawei_lun_wwn': lun_info['WWN']}) - model_update = {} - model_update.update({'admin_metadata': metadata}) - model_update.update({'provider_location': lun_id}) + location = huawei_utils.to_string(huawei_lun_id=lun_id, + huawei_lun_wwn=lun_info['WWN']) + model_update = {'provider_location': location} if new_opts and new_opts.get('replication_enabled'): LOG.debug("Manage volume need to create replication.") @@ -1565,9 +1580,9 @@ class HuaweiBaseDriver(driver.VolumeDriver): def manage_existing_snapshot(self, snapshot, existing_ref): snapshot_info = self._get_snapshot_info_by_ref(existing_ref) snapshot_id = snapshot_info.get('ID') - volume = snapshot.volume - lun_id = volume.provider_location - if lun_id != snapshot_info.get('PARENTID'): + parent_metadata = huawei_utils.get_lun_metadata(snapshot.volume) + parent_lun_id = parent_metadata.get('huawei_lun_id') + if parent_lun_id != snapshot_info.get('PARENTID'): msg = (_("Can't import snapshot %s to Cinder. " "Snapshot doesn't belong to volume."), snapshot_id) raise exception.ManageExistingInvalidReference( @@ -1587,7 +1602,8 @@ class HuaweiBaseDriver(driver.VolumeDriver): {'old_name': snapshot_info.get('NAME'), 'new_name': snapshot_name}) - return {'provider_location': snapshot_id} + location = huawei_utils.to_string(huawei_snapshot_id=snapshot_id) + return {'provider_location': location} def manage_existing_snapshot_get_size(self, snapshot, existing_ref): """Get the size of the existing snapshot.""" @@ -1702,9 +1718,11 @@ class HuaweiBaseDriver(driver.VolumeDriver): info = self.client.create_snapshot(lun_id, snapshot_name, snapshot_description) + location = huawei_utils.to_string( + huawei_snapshot_id=info['ID']) snap_model_update = {'id': snapshot.id, 'status': fields.SnapshotStatus.AVAILABLE, - 'provider_location': info['ID']} + 'provider_location': location} snapshots_model_update.append(snap_model_update) added_snapshots_info.append(info) except Exception: @@ -1874,7 +1892,8 @@ class HuaweiBaseDriver(driver.VolumeDriver): def get_lun_id_and_type(self, volume): if hasattr(volume, 'lun_type'): - lun_id = volume.provider_location + metadata = huawei_utils.get_snapshot_metadata(volume) + lun_id = metadata['huawei_snapshot_id'] lun_type = constants.SNAPSHOT_TYPE else: lun_id = self._check_volume_exist_on_array( @@ -2197,7 +2216,7 @@ class HuaweiFCDriver(HuaweiBaseDriver, driver.FibreChannelDriver): # Add host into hostgroup. hostgroup_id = self.client.add_host_to_hostgroup(host_id) - metadata = huawei_utils.get_volume_metadata(volume) + metadata = huawei_utils.get_lun_metadata(volume) LOG.info("initialize_connection, metadata is: %s.", metadata) hypermetro_lun = 'hypermetro_id' in metadata @@ -2356,7 +2375,7 @@ class HuaweiFCDriver(HuaweiBaseDriver, driver.FibreChannelDriver): self.client.delete_mapping_view(view_id) # Deal with hypermetro connection. - metadata = huawei_utils.get_volume_metadata(volume) + metadata = huawei_utils.get_lun_metadata(volume) LOG.info("Detach Volume, metadata is: %s.", metadata) if 'hypermetro_id' in metadata: diff --git a/cinder/volume/drivers/huawei/huawei_utils.py b/cinder/volume/drivers/huawei/huawei_utils.py index 012f1e7be13..c9f673054dd 100644 --- a/cinder/volume/drivers/huawei/huawei_utils.py +++ b/cinder/volume/drivers/huawei/huawei_utils.py @@ -13,6 +13,7 @@ # License for the specific language governing permissions and limitations # under the License. +import json import six import time @@ -124,3 +125,37 @@ def check_whether_operate_consistency_group(func): raise NotImplementedError(msg) return func(self, context, group, *args, **kwargs) return wrapper + + +def to_string(**kwargs): + return json.dumps(kwargs) if kwargs else '' + + +def get_lun_metadata(volume): + if not volume.provider_location: + return {} + + info = json.loads(volume.provider_location) + if isinstance(info, dict): + return info + + # To keep compatible with old driver version + admin_metadata = get_admin_metadata(volume) + metadata = get_volume_metadata(volume) + return {'huawei_lun_id': six.text_type(info), + 'huawei_lun_wwn': admin_metadata.get('huawei_lun_wwn'), + 'hypermetro_id': metadata.get('hypermetro_id'), + 'remote_lun_id': metadata.get('remote_lun_id') + } + + +def get_snapshot_metadata(snapshot): + if not snapshot.provider_location: + return {} + + info = json.loads(snapshot.provider_location) + if isinstance(info, dict): + return info + + # To keep compatible with old driver version + return {'huawei_snapshot_id': six.text_type(info)} diff --git a/cinder/volume/drivers/huawei/hypermetro.py b/cinder/volume/drivers/huawei/hypermetro.py index 9c7e36e8980..ff74858456a 100644 --- a/cinder/volume/drivers/huawei/hypermetro.py +++ b/cinder/volume/drivers/huawei/hypermetro.py @@ -75,7 +75,7 @@ class HuaweiHyperMetro(object): def delete_hypermetro(self, volume): """Delete hypermetro.""" - metadata = huawei_utils.get_volume_metadata(volume) + metadata = huawei_utils.get_lun_metadata(volume) metro_id = metadata['hypermetro_id'] remote_lun_id = metadata['remote_lun_id'] @@ -112,7 +112,7 @@ class HuaweiHyperMetro(object): {'wwpns': wwns, 'volume': volume_name}) - metadata = huawei_utils.get_volume_metadata(volume) + metadata = huawei_utils.get_lun_metadata(volume) lun_id = metadata['remote_lun_id'] if lun_id is None: @@ -185,7 +185,7 @@ class HuaweiHyperMetro(object): """Delete map between a volume and a host for FC.""" wwns = connector['wwpns'] volume_name = huawei_utils.encode_name(volume.id) - metadata = huawei_utils.get_volume_metadata(volume) + metadata = huawei_utils.get_lun_metadata(volume) lun_id = metadata['remote_lun_id'] host_name = connector['host'] left_lunnum = -1 @@ -331,7 +331,7 @@ class HuaweiHyperMetro(object): raise exception.VolumeBackendAPIException(data=msg) def check_metro_need_to_stop(self, volume): - metadata = huawei_utils.get_volume_metadata(volume) + metadata = huawei_utils.get_lun_metadata(volume) metro_id = metadata['hypermetro_id'] metro_existed = self.client.check_hypermetro_exist(metro_id) diff --git a/cinder/volume/drivers/huawei/replication.py b/cinder/volume/drivers/huawei/replication.py index 87d9e3c0a46..3a1b58e40cf 100644 --- a/cinder/volume/drivers/huawei/replication.py +++ b/cinder/volume/drivers/huawei/replication.py @@ -505,7 +505,8 @@ class ReplicaPairManager(object): model_update = {} driver_data = {'pair_id': pair_id, - 'rmt_lun_id': rmt_lun_id} + 'rmt_lun_id': rmt_lun_id, + 'rmt_lun_wwn': rmt_lun_info['WWN']} model_update['replication_driver_data'] = to_string(driver_data) model_update['replication_status'] = 'available' LOG.debug('Create replication, return info: %s.', model_update) @@ -582,16 +583,18 @@ class ReplicaPairManager(object): # Switch replication pair role, and start synchronize. self.rmt_driver.enable(pair_id) - lun_info = self.rmt_client.get_lun_info(rmt_lun_id) - admin_metadata = huawei_utils.get_admin_metadata(v) - admin_metadata.update({'huawei_lun_wwn': lun_info['WWN']}) - new_drv_data = {'pair_id': pair_id, - 'rmt_lun_id': v.provider_location} - new_drv_data = to_string(new_drv_data) - v_update['updates'] = {'provider_location': rmt_lun_id, + local_metadata = huawei_utils.get_lun_metadata(v) + new_drv_data = to_string( + {'pair_id': pair_id, + 'rmt_lun_id': local_metadata.get('huawei_lun_id'), + 'rmt_lun_wwn': local_metadata.get('huawei_lun_wwn')}) + location = huawei_utils.to_string( + huawei_lun_id=rmt_lun_id, + huawei_lun_wwn=drv_data.get('rmt_lun_wwn')) + + v_update['updates'] = {'provider_location': location, 'replication_status': 'available', - 'replication_driver_data': new_drv_data, - 'admin_metadata': admin_metadata} + 'replication_driver_data': new_drv_data} volumes_update.append(v_update) return volumes_update @@ -622,17 +625,18 @@ class ReplicaPairManager(object): self.rmt_driver.failover(pair_id) - lun_info = self.rmt_client.get_lun_info(rmt_lun_id) - admin_metadata = huawei_utils.get_admin_metadata(v) - admin_metadata.update({'huawei_lun_wwn': lun_info['WWN']}) + local_metadata = huawei_utils.get_lun_metadata(v) + new_drv_data = to_string( + {'pair_id': pair_id, + 'rmt_lun_id': local_metadata.get('huawei_lun_id'), + 'rmt_lun_wwn': local_metadata.get('huawei_lun_wwn')}) + location = huawei_utils.to_string( + huawei_lun_id=rmt_lun_id, + huawei_lun_wwn=drv_data.get('rmt_lun_wwn')) - new_drv_data = {'pair_id': pair_id, - 'rmt_lun_id': v.provider_location} - new_drv_data = to_string(new_drv_data) - v_update['updates'] = {'provider_location': rmt_lun_id, + v_update['updates'] = {'provider_location': location, 'replication_status': 'failed-over', - 'replication_driver_data': new_drv_data, - 'admin_metadata': admin_metadata} + 'replication_driver_data': new_drv_data} volumes_update.append(v_update) return volumes_update diff --git a/cinder/volume/drivers/huawei/rest_client.py b/cinder/volume/drivers/huawei/rest_client.py index feb95a3caad..0843baa93af 100644 --- a/cinder/volume/drivers/huawei/rest_client.py +++ b/cinder/volume/drivers/huawei/rest_client.py @@ -26,6 +26,7 @@ from cinder import exception from cinder.i18n import _ from cinder import utils from cinder.volume.drivers.huawei import constants +from cinder.volume.drivers.huawei import huawei_utils LOG = logging.getLogger(__name__) @@ -324,8 +325,10 @@ class RestClient(object): return result['data'] def get_lun_id(self, volume, volume_name): - lun_id = (volume.provider_location or + metadata = huawei_utils.get_lun_metadata(volume) + lun_id = (metadata.get('huawei_lun_id') or self.get_lun_id_by_name(volume_name)) + if not lun_id: msg = (_("Can't find lun info on the array. " "volume: %(id)s, lun name: %(name)s.") %