Merge "Change Huawei driver's private data storing place"

This commit is contained in:
Jenkins 2017-07-21 04:55:49 +00:00 committed by Gerrit Code Review
commit ac4284d63a
6 changed files with 340 additions and 152 deletions

View File

@ -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

View File

@ -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:

View File

@ -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)}

View File

@ -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)

View File

@ -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

View File

@ -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.") %