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
(cherry picked from commit 2d6ac671f2)
This commit is contained in:
zengyingzhe 2017-06-20 20:41:29 +08:00
parent 4c5a29a863
commit 10032adc6b
6 changed files with 350 additions and 159 deletions

View File

@ -21,11 +21,11 @@ import mock
import re
import requests
import tempfile
import unittest
from xml.dom import minidom
from cinder import context
from cinder import exception
from cinder.objects import fields
from cinder import test
from cinder.tests.unit.consistencygroup import fake_cgsnapshot
from cinder.tests.unit.consistencygroup import fake_consistencygroup
@ -50,15 +50,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": {
@ -499,7 +509,7 @@ FAKE_SNAPSHOT_LIST_INFO_RESPONSE = {
"description": "0"
},
"data": [{
"ID": 11,
"ID": "11",
"NAME": ENCODE_NAME
}, ]
}
@ -512,7 +522,7 @@ FAKE_CREATE_SNAPSHOT_INFO_RESPONSE = """
"code": 0
},
"data": {
"ID": 11,
"ID": "11",
"NAME": "YheUoRwbSX2BxN7"
}
}
@ -526,7 +536,7 @@ FAKE_GET_SNAPSHOT_INFO_RESPONSE = """
"description": "0"
},
"data": {
"ID": 11,
"ID": "11",
"NAME": "YheUoRwbSX2BxN7"
}
}
@ -2194,6 +2204,7 @@ class FakeFCStorage(huawei_driver.HuaweiFCDriver):
self.configuration)
@ddt.ddt
class HuaweiTestBase(test.TestCase):
"""Base class for Huawei test cases.
@ -2208,21 +2219,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)
@ -2248,12 +2260,83 @@ 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(
{
'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
@ -2338,12 +2421,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):
@ -2536,7 +2625,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,
@ -2544,13 +2632,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,
@ -2737,19 +2829,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
@ -2900,7 +2992,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']))
@mock.patch.object(huawei_driver.HuaweiBaseDriver, '_get_volume_params',
return_value={'smarttier': 'true',
@ -2923,7 +3018,10 @@ class HuaweiISCSIDriverTestCase(HuaweiTestBase):
mock_volume_params):
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],
@ -2989,7 +3087,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',
@ -3004,7 +3105,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',
@ -3092,7 +3196,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',
@ -3235,10 +3342,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',
@ -3479,12 +3589,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']])
@ -3580,12 +3688,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)
@ -3635,12 +3741,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',
@ -3696,9 +3804,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(
@ -3815,7 +3924,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,
@ -3834,7 +3942,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
@ -3851,7 +3958,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,
@ -3979,12 +4085,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):
@ -4037,12 +4150,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):
@ -4072,7 +4192,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',
@ -4128,7 +4247,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)
@ -4235,15 +4353,16 @@ class HuaweiISCSIDriverTestCase(HuaweiTestBase):
def test_create_cgsnapshot(self):
test_snapshots = [self.snapshot]
ctxt = context.get_admin_context()
model, snapshots = self.driver.create_cgsnapshot(ctxt,
self.cgsnapshot,
test_snapshots)
snapshots_model_update = [{'id': '21ec7341-9256-497b-97d9'
'-ef48edcf0635',
'status': 'available',
'provider_location': 11}]
self.assertEqual(snapshots_model_update, snapshots)
self.assertEqual('available', model['status'])
model, snapshots = (
self.driver.create_cgsnapshot(ctxt, self.cgsnapshot,
test_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'])
def test_create_cgsnapshot_create_snapshot_fail(self):
test_snapshots = [self.snapshot]
@ -4304,7 +4423,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):
@ -4314,11 +4436,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',
@ -4530,7 +4654,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,
@ -4612,13 +4735,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',
@ -4667,7 +4792,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(
@ -4858,7 +4982,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 = {}
@ -4922,10 +5049,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',
@ -4954,7 +5084,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',
@ -4968,13 +5098,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',
@ -4982,15 +5112,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',
@ -5002,7 +5131,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):
@ -5120,7 +5249,7 @@ class HuaweiFCDriverTestCase(HuaweiTestBase):
@mock.patch.object(huawei_driver.HuaweiBaseDriver,
'_get_consistencygroup_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'})
def test_update_consistencygroup_success(self,

View File

@ -29,6 +29,7 @@ from cinder import context
from cinder import exception
from cinder.i18n import _, _LE, _LI, _LW
from cinder import interface
from cinder.objects import fields
from cinder import utils
from cinder.volume import driver
from cinder.volume.drivers.huawei import constants
@ -333,17 +334,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):
@ -352,7 +349,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:
@ -427,10 +424,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
@ -459,7 +461,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,
@ -647,7 +649,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
@ -667,9 +671,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'],
@ -681,8 +688,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():
@ -724,7 +735,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:
@ -738,7 +750,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(_LI(
'create_volume_from_snapshot: src_lun_id: %(src_lun_id)s, '
@ -768,6 +780,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):
@ -807,7 +822,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)
@ -821,8 +837,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)
@ -898,7 +913,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):
@ -911,7 +927,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)
@ -1186,7 +1203,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']
@ -1463,12 +1481,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.")
@ -1552,9 +1568,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(
@ -1574,7 +1590,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."""
@ -1679,10 +1696,12 @@ class HuaweiBaseDriver(driver.VolumeDriver):
info = self.client.create_snapshot(lun_id,
snapshot_name,
snapshot_description)
snapshot_model_update = {'id': snapshot.id,
'status': 'available',
'provider_location': info['ID']}
snapshots_model_update.append(snapshot_model_update)
location = huawei_utils.to_string(
huawei_snapshot_id=info['ID'])
snap_model_update = {'id': snapshot.id,
'status': fields.SnapshotStatus.AVAILABLE,
'provider_location': location}
snapshots_model_update.append(snap_model_update)
added_snapshots_info.append(info)
except Exception:
with excutils.save_and_reraise_exception():
@ -1849,7 +1868,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(
@ -2171,7 +2191,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(_LI("initialize_connection, metadata is: %s."), metadata)
hypermetro_lun = 'hypermetro_id' in metadata
@ -2330,7 +2350,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(_LI("Detach Volume, metadata is: %s."), metadata)
if 'hypermetro_id' in metadata:

View File

@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import json
import six
import time
@ -112,3 +113,37 @@ def get_snapshot_metadata_value(snapshot):
return {item['key']: item['value'] for item in metadata}
return {}
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)}

View File

@ -74,7 +74,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']
@ -111,7 +111,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:
@ -184,7 +184,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
@ -332,7 +332,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)

View File

@ -506,7 +506,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)
@ -583,16 +584,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
@ -623,17 +626,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

View File

@ -26,6 +26,7 @@ from cinder import exception
from cinder.i18n import _, _LE, _LI, _LW
from cinder import utils
from cinder.volume.drivers.huawei import constants
from cinder.volume.drivers.huawei import huawei_utils
LOG = logging.getLogger(__name__)
@ -322,8 +323,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.") %