Hitachi: Support for QoS
This patch supports for QoS on Hitachi driver. Implements: blueprint hitachi-vsp-add-qos Change-Id: Ib9f6d1c845f374aef86583a5e8d75429f02503e8
This commit is contained in:
parent
8dce75e1d0
commit
c90d898744
@ -104,12 +104,12 @@ REMOTE_DEFAULT_CONNECTOR = {
|
|||||||
CTXT = cinder_context.get_admin_context()
|
CTXT = cinder_context.get_admin_context()
|
||||||
|
|
||||||
TEST_VOLUME = []
|
TEST_VOLUME = []
|
||||||
for i in range(7):
|
for i in range(8):
|
||||||
volume = {}
|
volume = {}
|
||||||
volume['id'] = '00000000-0000-0000-0000-{0:012d}'.format(i)
|
volume['id'] = '00000000-0000-0000-0000-{0:012d}'.format(i)
|
||||||
volume['name'] = 'test-volume{0:d}'.format(i)
|
volume['name'] = 'test-volume{0:d}'.format(i)
|
||||||
volume['volume_type_id'] = '00000000-0000-0000-0000-{0:012d}'.format(i)
|
volume['volume_type_id'] = '00000000-0000-0000-0000-{0:012d}'.format(i)
|
||||||
if i == 3:
|
if i == 3 or i == 7:
|
||||||
volume['provider_location'] = None
|
volume['provider_location'] = None
|
||||||
elif i == 4:
|
elif i == 4:
|
||||||
volume['provider_location'] = json.dumps(
|
volume['provider_location'] = json.dumps(
|
||||||
@ -128,6 +128,8 @@ for i in range(7):
|
|||||||
volume['size'] = 128
|
volume['size'] = 128
|
||||||
if i == 2 or i == 6:
|
if i == 2 or i == 6:
|
||||||
volume['status'] = 'in-use'
|
volume['status'] = 'in-use'
|
||||||
|
elif i == 7:
|
||||||
|
volume['status'] = None
|
||||||
else:
|
else:
|
||||||
volume['status'] = 'available'
|
volume['status'] = 'available'
|
||||||
volume = fake_volume.fake_volume_obj(CTXT, **volume)
|
volume = fake_volume.fake_volume_obj(CTXT, **volume)
|
||||||
@ -826,9 +828,12 @@ class HBSDMIRRORFCDriverTest(test.TestCase):
|
|||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
def test_create_volume(self, get_volume_type_extra_specs, request):
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_volume(self, get_volume_type_qos_specs,
|
||||||
|
get_volume_type_extra_specs, request):
|
||||||
extra_specs = {"test1": "aaa"}
|
extra_specs = {"test1": "aaa"}
|
||||||
get_volume_type_extra_specs.return_value = extra_specs
|
get_volume_type_extra_specs.return_value = extra_specs
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
request.return_value = FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)
|
request.return_value = FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)
|
||||||
self.driver.common.rep_primary._stats = {}
|
self.driver.common.rep_primary._stats = {}
|
||||||
self.driver.common.rep_primary._stats['pools'] = [
|
self.driver.common.rep_primary._stats['pools'] = [
|
||||||
@ -836,20 +841,20 @@ class HBSDMIRRORFCDriverTest(test.TestCase):
|
|||||||
self.driver.common.rep_secondary._stats = {}
|
self.driver.common.rep_secondary._stats = {}
|
||||||
self.driver.common.rep_secondary._stats['pools'] = [
|
self.driver.common.rep_secondary._stats['pools'] = [
|
||||||
{'location_info': {'pool_id': 40}}]
|
{'location_info': {'pool_id': 40}}]
|
||||||
ret = self.driver.create_volume(fake_volume.fake_volume_obj(self.ctxt))
|
ret = self.driver.create_volume(TEST_VOLUME[7])
|
||||||
actual = {'provider_location': '1'}
|
actual = {'provider_location': '1'}
|
||||||
self.assertEqual(actual, ret)
|
self.assertEqual(actual, ret)
|
||||||
self.assertEqual(2, request.call_count)
|
self.assertEqual(2, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@mock.patch.object(volume_types, 'get_volume_type')
|
|
||||||
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
def test_create_volume_replication(
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
self, get_volume_type_extra_specs, get_volume_type, request):
|
def test_create_volume_replication(self, get_volume_type_qos_specs,
|
||||||
|
get_volume_type_extra_specs, request):
|
||||||
extra_specs = {"test1": "aaa",
|
extra_specs = {"test1": "aaa",
|
||||||
"hbsd:topology": "active_active_mirror_volume"}
|
"hbsd:topology": "active_active_mirror_volume"}
|
||||||
get_volume_type_extra_specs.return_value = extra_specs
|
get_volume_type_extra_specs.return_value = extra_specs
|
||||||
get_volume_type.return_value = {}
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
|
|
||||||
def _request_side_effect(
|
def _request_side_effect(
|
||||||
method, url, params, json, headers, auth, timeout, verify):
|
method, url, params, json, headers, auth, timeout, verify):
|
||||||
@ -885,6 +890,57 @@ class HBSDMIRRORFCDriverTest(test.TestCase):
|
|||||||
self.assertEqual(actual, ret)
|
self.assertEqual(actual, ret)
|
||||||
self.assertEqual(14, request.call_count)
|
self.assertEqual(14, request.call_count)
|
||||||
|
|
||||||
|
@mock.patch.object(requests.Session, "request")
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_volume_replication_qos(
|
||||||
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
|
input_qos_specs = {
|
||||||
|
'qos_specs': {
|
||||||
|
'consumer': 'back-end',
|
||||||
|
'specs': {'upperIops': '1000'}}}
|
||||||
|
get_volume_type_qos_specs.return_value = input_qos_specs
|
||||||
|
extra_specs = {"test1": "aaa",
|
||||||
|
"hbsd:topology": "active_active_mirror_volume"}
|
||||||
|
get_volume_type_extra_specs.return_value = extra_specs
|
||||||
|
|
||||||
|
def _request_side_effect(
|
||||||
|
method, url, params, json, headers, auth, timeout, verify):
|
||||||
|
if self.configuration.hitachi_storage_id in url:
|
||||||
|
if method in ('POST', 'PUT'):
|
||||||
|
return FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)
|
||||||
|
elif method == 'GET':
|
||||||
|
if '/remote-mirror-copygroups' in url:
|
||||||
|
return FakeResponse(200, NOTFOUND_RESULT)
|
||||||
|
elif '/remote-mirror-copypairs/' in url:
|
||||||
|
return FakeResponse(
|
||||||
|
200, GET_REMOTE_MIRROR_COPYPAIR_RESULT)
|
||||||
|
else:
|
||||||
|
if method in ('POST', 'PUT'):
|
||||||
|
return FakeResponse(202, REMOTE_COMPLETED_SUCCEEDED_RESULT)
|
||||||
|
elif method == 'GET':
|
||||||
|
if '/remote-mirror-copygroups' in url:
|
||||||
|
return FakeResponse(200, NOTFOUND_RESULT)
|
||||||
|
return FakeResponse(
|
||||||
|
500, ERROR_RESULT, headers={'Content-Type': 'json'})
|
||||||
|
request.side_effect = _request_side_effect
|
||||||
|
self.driver.common.rep_primary._stats = {}
|
||||||
|
self.driver.common.rep_primary._stats['pools'] = [
|
||||||
|
{'location_info': {'pool_id': 30}}]
|
||||||
|
self.driver.common.rep_secondary._stats = {}
|
||||||
|
self.driver.common.rep_secondary._stats['pools'] = [
|
||||||
|
{'location_info': {'pool_id': 40}}]
|
||||||
|
ret = self.driver.create_volume(TEST_VOLUME[3])
|
||||||
|
actual = {
|
||||||
|
'provider_location': json.dumps(
|
||||||
|
{'pldev': 1, 'sldev': 2,
|
||||||
|
'remote-copy': hbsd_utils.MIRROR_ATTR})}
|
||||||
|
self.assertEqual(actual, ret)
|
||||||
|
self.assertEqual(1, get_volume_type_extra_specs.call_count)
|
||||||
|
self.assertEqual(1, get_volume_type_qos_specs.call_count)
|
||||||
|
self.assertEqual(16, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_delete_volume(self, request):
|
def test_delete_volume(self, request):
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
@ -1028,11 +1084,14 @@ class HBSDMIRRORFCDriverTest(test.TestCase):
|
|||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
def test_create_snapshot(
|
def test_create_snapshot(
|
||||||
self, volume_get, get_volume_type_extra_specs, request):
|
self, get_volume_type_qos_specs, volume_get,
|
||||||
|
get_volume_type_extra_specs, request):
|
||||||
extra_specs = {"test1": "aaa",
|
extra_specs = {"test1": "aaa",
|
||||||
"hbsd:topology": "active_active_mirror_volume"}
|
"hbsd:topology": "active_active_mirror_volume"}
|
||||||
get_volume_type_extra_specs.return_value = extra_specs
|
get_volume_type_extra_specs.return_value = extra_specs
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
@ -1086,13 +1145,14 @@ class HBSDMIRRORFCDriverTest(test.TestCase):
|
|||||||
self.assertEqual(3, request.call_count)
|
self.assertEqual(3, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@mock.patch.object(volume_types, 'get_volume_type')
|
|
||||||
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
def test_create_cloned_volume(
|
def test_create_cloned_volume(
|
||||||
self, get_volume_type_extra_specs, get_volume_type, request):
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
extra_specs = {"test1": "aaa"}
|
extra_specs = {"test1": "aaa"}
|
||||||
get_volume_type_extra_specs.return_value = extra_specs
|
get_volume_type_extra_specs.return_value = extra_specs
|
||||||
get_volume_type.return_value = {}
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
@ -1110,14 +1170,14 @@ class HBSDMIRRORFCDriverTest(test.TestCase):
|
|||||||
self.assertEqual(5, request.call_count)
|
self.assertEqual(5, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@mock.patch.object(volume_types, 'get_volume_type')
|
|
||||||
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
def test_create_cloned_volume_replication(
|
def test_create_cloned_volume_replication(
|
||||||
self, get_volume_type_extra_specs, get_volume_type, request):
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
extra_specs = {"test1": "aaa",
|
request):
|
||||||
"hbsd:topology": "active_active_mirror_volume"}
|
extra_specs = {"hbsd:topology": "active_active_mirror_volume"}
|
||||||
get_volume_type_extra_specs.return_value = extra_specs
|
get_volume_type_extra_specs.return_value = extra_specs
|
||||||
get_volume_type.return_value = {}
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
self.snapshot_count = 0
|
self.snapshot_count = 0
|
||||||
|
|
||||||
def _request_side_effect(
|
def _request_side_effect(
|
||||||
@ -1163,13 +1223,14 @@ class HBSDMIRRORFCDriverTest(test.TestCase):
|
|||||||
self.assertEqual(23, request.call_count)
|
self.assertEqual(23, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@mock.patch.object(volume_types, 'get_volume_type')
|
|
||||||
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
def test_create_volume_from_snapshot(
|
def test_create_volume_from_snapshot(
|
||||||
self, get_volume_type_extra_specs, get_volume_type, request):
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
extra_specs = {"test1": "aaa"}
|
extra_specs = {"test1": "aaa"}
|
||||||
get_volume_type_extra_specs.return_value = extra_specs
|
get_volume_type_extra_specs.return_value = extra_specs
|
||||||
get_volume_type.return_value = {}
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
@ -1288,16 +1349,17 @@ class HBSDMIRRORFCDriverTest(test.TestCase):
|
|||||||
self.assertEqual(1, remove_fc_zone.call_count)
|
self.assertEqual(1, remove_fc_zone.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@mock.patch.object(volume_types, 'get_volume_type')
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
def test_manage_existing(self, get_volume_type, request):
|
def test_manage_existing(self, get_volume_type_qos_specs, request):
|
||||||
get_volume_type.return_value = {}
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
|
FakeResponse(200, GET_LDEVS_RESULT)]
|
||||||
ret = self.driver.manage_existing(
|
ret = self.driver.manage_existing(
|
||||||
TEST_VOLUME[0], self.test_existing_ref)
|
TEST_VOLUME[0], self.test_existing_ref)
|
||||||
actual = {'provider_location': '1'}
|
actual = {'provider_location': '1'}
|
||||||
self.assertEqual(actual, ret)
|
self.assertEqual(actual, ret)
|
||||||
self.assertEqual(2, request.call_count)
|
self.assertEqual(3, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
@ -1483,13 +1545,14 @@ class HBSDMIRRORFCDriverTest(test.TestCase):
|
|||||||
self.assertTupleEqual(actual, ret)
|
self.assertTupleEqual(actual, ret)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@mock.patch.object(volume_types, 'get_volume_type')
|
|
||||||
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
def test_create_group_from_src_volume(
|
def test_create_group_from_src_volume(
|
||||||
self, get_volume_type_extra_specs, get_volume_type, request):
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
extra_specs = {"test1": "aaa"}
|
extra_specs = {"test1": "aaa"}
|
||||||
get_volume_type_extra_specs.return_value = extra_specs
|
get_volume_type_extra_specs.return_value = extra_specs
|
||||||
get_volume_type.return_value = {}
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
@ -1513,13 +1576,14 @@ class HBSDMIRRORFCDriverTest(test.TestCase):
|
|||||||
self.assertTupleEqual(actual, ret)
|
self.assertTupleEqual(actual, ret)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@mock.patch.object(volume_types, 'get_volume_type')
|
|
||||||
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
def test_create_group_from_src_Exception(
|
def test_create_group_from_src_Exception(
|
||||||
self, get_volume_type_extra_specs, get_volume_type, request):
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
extra_specs = {"test1": "aaa"}
|
extra_specs = {"test1": "aaa"}
|
||||||
get_volume_type_extra_specs.return_value = extra_specs
|
get_volume_type_extra_specs.return_value = extra_specs
|
||||||
get_volume_type.return_value = {}
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
@ -1546,13 +1610,14 @@ class HBSDMIRRORFCDriverTest(test.TestCase):
|
|||||||
self.assertEqual(10, request.call_count)
|
self.assertEqual(10, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@mock.patch.object(volume_types, 'get_volume_type')
|
|
||||||
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
def test_create_group_from_src_snapshot(
|
def test_create_group_from_src_snapshot(
|
||||||
self, get_volume_type_extra_specs, get_volume_type, request):
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
extra_specs = {"test1": "aaa"}
|
extra_specs = {"test1": "aaa"}
|
||||||
get_volume_type_extra_specs.return_value = extra_specs
|
get_volume_type_extra_specs.return_value = extra_specs
|
||||||
get_volume_type.return_value = {}
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
@ -1586,12 +1651,14 @@ class HBSDMIRRORFCDriverTest(test.TestCase):
|
|||||||
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
||||||
@mock.patch.object(volume_utils, 'is_group_a_cg_snapshot_type')
|
@mock.patch.object(volume_utils, 'is_group_a_cg_snapshot_type')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
def test_create_group_snapshot_non_cg(
|
def test_create_group_snapshot_non_cg(
|
||||||
self, is_group_a_cg_snapshot_type, volume_get,
|
self, get_volume_type_qos_specs, is_group_a_cg_snapshot_type,
|
||||||
get_volume_type_extra_specs, request):
|
volume_get, get_volume_type_extra_specs, request):
|
||||||
is_group_a_cg_snapshot_type.return_value = False
|
is_group_a_cg_snapshot_type.return_value = False
|
||||||
extra_specs = {"test1": "aaa"}
|
extra_specs = {"test1": "aaa"}
|
||||||
get_volume_type_extra_specs.return_value = extra_specs
|
get_volume_type_extra_specs.return_value = extra_specs
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
@ -1641,14 +1708,15 @@ class HBSDMIRRORFCDriverTest(test.TestCase):
|
|||||||
self.assertTupleEqual(actual, ret)
|
self.assertTupleEqual(actual, ret)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@mock.patch.object(volume_types, 'get_volume_type')
|
|
||||||
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
def test_create_rep_ldev_and_pair_deduplication_compression(
|
def test_create_rep_ldev_and_pair_deduplication_compression(
|
||||||
self, get_volume_type_extra_specs, get_volume_type, request):
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
get_volume_type_extra_specs.return_value = {
|
get_volume_type_extra_specs.return_value = {
|
||||||
'hbsd:topology': 'active_active_mirror_volume',
|
'hbsd:topology': 'active_active_mirror_volume',
|
||||||
'hbsd:capacity_saving': 'deduplication_compression'}
|
'hbsd:capacity_saving': 'deduplication_compression'}
|
||||||
get_volume_type.return_value = {}
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
self.snapshot_count = 0
|
self.snapshot_count = 0
|
||||||
|
|
||||||
def _request_side_effect(
|
def _request_side_effect(
|
||||||
@ -1696,5 +1764,5 @@ class HBSDMIRRORFCDriverTest(test.TestCase):
|
|||||||
TEST_VOLUME[4],
|
TEST_VOLUME[4],
|
||||||
TEST_VOLUME[5])
|
TEST_VOLUME[5])
|
||||||
self.assertEqual(2, get_volume_type_extra_specs.call_count)
|
self.assertEqual(2, get_volume_type_extra_specs.call_count)
|
||||||
self.assertEqual(0, get_volume_type.call_count)
|
self.assertEqual(1, get_volume_type_qos_specs.call_count)
|
||||||
self.assertEqual(14, request.call_count)
|
self.assertEqual(14, request.call_count)
|
||||||
|
@ -94,18 +94,20 @@ DEFAULT_CONNECTOR_MULTI_WWN = {
|
|||||||
CTXT = cinder_context.get_admin_context()
|
CTXT = cinder_context.get_admin_context()
|
||||||
|
|
||||||
TEST_VOLUME = []
|
TEST_VOLUME = []
|
||||||
for i in range(4):
|
for i in range(5):
|
||||||
volume = {}
|
volume = {}
|
||||||
volume['id'] = '00000000-0000-0000-0000-{0:012d}'.format(i)
|
volume['id'] = '00000000-0000-0000-0000-{0:012d}'.format(i)
|
||||||
volume['name'] = 'test-volume{0:d}'.format(i)
|
volume['name'] = 'test-volume{0:d}'.format(i)
|
||||||
volume['volume_type_id'] = '00000000-0000-0000-0000-{0:012d}'.format(i)
|
volume['volume_type_id'] = '00000000-0000-0000-0000-{0:012d}'.format(i)
|
||||||
if i == 3:
|
if i == 3 or i == 4:
|
||||||
volume['provider_location'] = None
|
volume['provider_location'] = None
|
||||||
else:
|
else:
|
||||||
volume['provider_location'] = '{0:d}'.format(i)
|
volume['provider_location'] = '{0:d}'.format(i)
|
||||||
volume['size'] = 128
|
volume['size'] = 128
|
||||||
if i == 2:
|
if i == 2:
|
||||||
volume['status'] = 'in-use'
|
volume['status'] = 'in-use'
|
||||||
|
elif i == 4:
|
||||||
|
volume['status'] = None
|
||||||
else:
|
else:
|
||||||
volume['status'] = 'available'
|
volume['status'] = 'available'
|
||||||
volume = fake_volume.fake_volume_obj(CTXT, **volume)
|
volume = fake_volume.fake_volume_obj(CTXT, **volume)
|
||||||
@ -394,6 +396,16 @@ GET_LDEVS_RESULT = {
|
|||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GET_LDEVS_RESULT_QOS = {
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"ldevId": 0,
|
||||||
|
"label": "15960cc738c94c5bb4f1365be5eeed44",
|
||||||
|
"qos": {"upperIops": 1000},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
NOTFOUND_RESULT = {
|
NOTFOUND_RESULT = {
|
||||||
"data": [],
|
"data": [],
|
||||||
}
|
}
|
||||||
@ -814,21 +826,29 @@ class HBSDRESTFCDriverTest(test.TestCase):
|
|||||||
drv.common.client.keep_session_loop.stop()
|
drv.common.client.keep_session_loop.stop()
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_create_volume(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_volume(self, get_volume_type_qos_specs,
|
||||||
|
get_volume_type_extra_specs, request):
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
request.return_value = FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)
|
request.return_value = FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)
|
||||||
self.driver.common._stats = {}
|
self.driver.common._stats = {}
|
||||||
self.driver.common._stats['pools'] = [
|
self.driver.common._stats['pools'] = [
|
||||||
{'location_info': {'pool_id': 30}}]
|
{'location_info': {'pool_id': 30}}]
|
||||||
ret = self.driver.create_volume(fake_volume.fake_volume_obj(self.ctxt))
|
ret = self.driver.create_volume(TEST_VOLUME[4])
|
||||||
self.assertEqual('1', ret['provider_location'])
|
self.assertEqual('1', ret['provider_location'])
|
||||||
self.assertEqual(2, request.call_count)
|
self.assertEqual(2, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
def test_create_volume_deduplication_compression(
|
def test_create_volume_deduplication_compression(
|
||||||
self, get_volume_type_extra_specs, request):
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
extra_specs = {'hbsd:capacity_saving': 'deduplication_compression'}
|
extra_specs = {'hbsd:capacity_saving': 'deduplication_compression'}
|
||||||
get_volume_type_extra_specs.return_value = extra_specs
|
get_volume_type_extra_specs.return_value = extra_specs
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
request.return_value = FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)
|
request.return_value = FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)
|
||||||
self.driver.common._stats = {}
|
self.driver.common._stats = {}
|
||||||
self.driver.common._stats['pools'] = [
|
self.driver.common._stats['pools'] = [
|
||||||
@ -840,13 +860,19 @@ class HBSDRESTFCDriverTest(test.TestCase):
|
|||||||
'compression_deduplication')
|
'compression_deduplication')
|
||||||
self.assertEqual('1', ret['provider_location'])
|
self.assertEqual('1', ret['provider_location'])
|
||||||
self.assertEqual(1, get_volume_type_extra_specs.call_count)
|
self.assertEqual(1, get_volume_type_extra_specs.call_count)
|
||||||
|
self.assertEqual(1, get_volume_type_qos_specs.call_count)
|
||||||
self.assertEqual(2, request.call_count)
|
self.assertEqual(2, request.call_count)
|
||||||
|
|
||||||
@reduce_retrying_time
|
@reduce_retrying_time
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_create_volume_timeout(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_volume_timeout(self, get_volume_type_qos_specs,
|
||||||
|
get_volume_type_extra_specs, request):
|
||||||
self.driver.common.conf.hitachi_rest_timeout = 0
|
self.driver.common.conf.hitachi_rest_timeout = 0
|
||||||
self.driver.common.conf.hitachi_exec_retry_interval = 0
|
self.driver.common.conf.hitachi_exec_retry_interval = 0
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
request.return_value = FakeResponse(
|
request.return_value = FakeResponse(
|
||||||
500, ERROR_RESULT,
|
500, ERROR_RESULT,
|
||||||
headers={'Content-Type': 'json'})
|
headers={'Content-Type': 'json'})
|
||||||
@ -856,9 +882,46 @@ class HBSDRESTFCDriverTest(test.TestCase):
|
|||||||
{'location_info': {'pool_id': 30}}]
|
{'location_info': {'pool_id': 30}}]
|
||||||
self.assertRaises(exception.VolumeDriverException,
|
self.assertRaises(exception.VolumeDriverException,
|
||||||
self.driver.create_volume,
|
self.driver.create_volume,
|
||||||
fake_volume.fake_volume_obj(self.ctxt))
|
TEST_VOLUME[4])
|
||||||
self.assertGreater(request.call_count, 1)
|
self.assertGreater(request.call_count, 1)
|
||||||
|
|
||||||
|
@mock.patch.object(requests.Session, "request")
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_volume_qos(self, get_volume_type_qos_specs,
|
||||||
|
get_volume_type_extra_specs, request):
|
||||||
|
specs = {}
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
input_qos_specs = {
|
||||||
|
'qos_specs': {
|
||||||
|
'consumer': 'back-end',
|
||||||
|
'specs': {'upperIops': '1000',
|
||||||
|
'upperTransferRate': '2000',
|
||||||
|
'lowerIops': '3000',
|
||||||
|
'lowerTransferRate': '4000',
|
||||||
|
'responsePriority': '3'}}}
|
||||||
|
get_volume_type_qos_specs.return_value = input_qos_specs
|
||||||
|
request.return_value = FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)
|
||||||
|
self.driver.common._stats = {}
|
||||||
|
self.driver.common._stats['pools'] = [
|
||||||
|
{'location_info': {'pool_id': 30}}]
|
||||||
|
ret = self.driver.create_volume(TEST_VOLUME[0])
|
||||||
|
for i in range(1, 6):
|
||||||
|
args, kwargs = request.call_args_list[i]
|
||||||
|
body = kwargs['json']
|
||||||
|
for key, value in body['parameters'].items():
|
||||||
|
specs[key] = value
|
||||||
|
|
||||||
|
self.assertEqual(specs['upperIops'], 1000)
|
||||||
|
self.assertEqual(specs['upperTransferRate'], 2000)
|
||||||
|
self.assertEqual(specs['lowerIops'], 3000)
|
||||||
|
self.assertEqual(specs['lowerTransferRate'], 4000)
|
||||||
|
self.assertEqual(specs['responsePriority'], 3)
|
||||||
|
self.assertEqual('1', ret['provider_location'])
|
||||||
|
self.assertEqual(1, get_volume_type_extra_specs.call_count)
|
||||||
|
self.assertEqual(1, get_volume_type_qos_specs.call_count)
|
||||||
|
self.assertEqual(7, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_delete_volume(self, request):
|
def test_delete_volume(self, request):
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
@ -932,6 +995,7 @@ class HBSDRESTFCDriverTest(test.TestCase):
|
|||||||
stats["pools"][0]['pool_name'])
|
stats["pools"][0]['pool_name'])
|
||||||
self.assertEqual(self.configuration.reserved_percentage,
|
self.assertEqual(self.configuration.reserved_percentage,
|
||||||
stats["pools"][0]['reserved_percentage'])
|
stats["pools"][0]['reserved_percentage'])
|
||||||
|
self.assertTrue(stats["pools"][0]['QoS_support'])
|
||||||
self.assertTrue(stats["pools"][0]['thin_provisioning_support'])
|
self.assertTrue(stats["pools"][0]['thin_provisioning_support'])
|
||||||
self.assertFalse(stats["pools"][0]['thick_provisioning_support'])
|
self.assertFalse(stats["pools"][0]['thick_provisioning_support'])
|
||||||
self.assertTrue(stats["pools"][0]['multiattach'])
|
self.assertTrue(stats["pools"][0]['multiattach'])
|
||||||
@ -985,14 +1049,17 @@ class HBSDRESTFCDriverTest(test.TestCase):
|
|||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
def test_create_snapshot(
|
def test_create_snapshot(
|
||||||
self, volume_get, get_volume_type_extra_specs, request):
|
self, get_volume_type_qos_specs, volume_get,
|
||||||
|
get_volume_type_extra_specs, request):
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
||||||
get_volume_type_extra_specs.return_value = {}
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
self.driver.common._stats = {}
|
self.driver.common._stats = {}
|
||||||
self.driver.common._stats['pools'] = [
|
self.driver.common._stats['pools'] = [
|
||||||
{'location_info': {'pool_id': 30}}]
|
{'location_info': {'pool_id': 30}}]
|
||||||
@ -1004,8 +1071,10 @@ class HBSDRESTFCDriverTest(test.TestCase):
|
|||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
def test_create_snapshot_dedup_false(
|
def test_create_snapshot_dedup_false(
|
||||||
self, volume_get, get_volume_type_extra_specs, request):
|
self, get_volume_type_qos_specs, volume_get,
|
||||||
|
get_volume_type_extra_specs, request):
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
@ -1013,6 +1082,7 @@ class HBSDRESTFCDriverTest(test.TestCase):
|
|||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
||||||
get_volume_type_extra_specs.return_value = {'hbsd:capacity_saving':
|
get_volume_type_extra_specs.return_value = {'hbsd:capacity_saving':
|
||||||
'disable'}
|
'disable'}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
self.driver.common._stats = {}
|
self.driver.common._stats = {}
|
||||||
self.driver.common._stats['pools'] = [
|
self.driver.common._stats['pools'] = [
|
||||||
{'location_info': {'pool_id': 30}}]
|
{'location_info': {'pool_id': 30}}]
|
||||||
@ -1052,26 +1122,31 @@ class HBSDRESTFCDriverTest(test.TestCase):
|
|||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
def test_create_cloned_volume(
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
self, get_volume_type_extra_specs, request):
|
def test_create_cloned_volume(self, get_volume_type_qos_specs,
|
||||||
|
get_volume_type_extra_specs, request):
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
||||||
get_volume_type_extra_specs.return_value = {}
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
self.driver.common._stats = {}
|
self.driver.common._stats = {}
|
||||||
self.driver.common._stats['pools'] = [
|
self.driver.common._stats['pools'] = [
|
||||||
{'location_info': {'pool_id': 30}}]
|
{'location_info': {'pool_id': 30}}]
|
||||||
vol = self.driver.create_cloned_volume(TEST_VOLUME[0], TEST_VOLUME[1])
|
vol = self.driver.create_cloned_volume(TEST_VOLUME[0], TEST_VOLUME[1])
|
||||||
self.assertEqual('1', vol['provider_location'])
|
self.assertEqual('1', vol['provider_location'])
|
||||||
self.assertEqual(1, get_volume_type_extra_specs.call_count)
|
self.assertEqual(1, get_volume_type_extra_specs.call_count)
|
||||||
|
self.assertEqual(1, get_volume_type_qos_specs.call_count)
|
||||||
self.assertEqual(5, request.call_count)
|
self.assertEqual(5, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
def test_create_volume_from_snapshot(
|
def test_create_volume_from_snapshot(
|
||||||
self, get_volume_type_extra_specs, request):
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
@ -1079,12 +1154,14 @@ class HBSDRESTFCDriverTest(test.TestCase):
|
|||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
||||||
self.driver.common._stats = {}
|
self.driver.common._stats = {}
|
||||||
get_volume_type_extra_specs.return_value = {}
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
self.driver.common._stats['pools'] = [
|
self.driver.common._stats['pools'] = [
|
||||||
{'location_info': {'pool_id': 30}}]
|
{'location_info': {'pool_id': 30}}]
|
||||||
vol = self.driver.create_volume_from_snapshot(
|
vol = self.driver.create_volume_from_snapshot(
|
||||||
TEST_VOLUME[0], TEST_SNAPSHOT[0])
|
TEST_VOLUME[0], TEST_SNAPSHOT[0])
|
||||||
self.assertEqual('1', vol['provider_location'])
|
self.assertEqual('1', vol['provider_location'])
|
||||||
self.assertEqual(1, get_volume_type_extra_specs.call_count)
|
self.assertEqual(1, get_volume_type_extra_specs.call_count)
|
||||||
|
self.assertEqual(1, get_volume_type_qos_specs.call_count)
|
||||||
self.assertEqual(5, request.call_count)
|
self.assertEqual(5, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(fczm_utils, "add_fc_zone")
|
@mock.patch.object(fczm_utils, "add_fc_zone")
|
||||||
@ -1256,23 +1333,49 @@ class HBSDRESTFCDriverTest(test.TestCase):
|
|||||||
self.assertEqual(1, remove_fc_zone.call_count)
|
self.assertEqual(1, remove_fc_zone.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_manage_existing(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_manage_existing(self, get_volume_type_qos_specs, request):
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
|
FakeResponse(200, GET_LDEVS_RESULT)]
|
||||||
|
ret = self.driver.manage_existing(
|
||||||
|
TEST_VOLUME[0], self.test_existing_ref)
|
||||||
|
self.assertEqual('1', ret['provider_location'])
|
||||||
|
self.assertEqual(1, get_volume_type_qos_specs.call_count)
|
||||||
|
self.assertEqual(3, request.call_count)
|
||||||
|
|
||||||
|
@mock.patch.object(requests.Session, "request")
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_manage_existing_qos(self, get_volume_type_qos_specs, request):
|
||||||
|
input_qos_specs = {
|
||||||
|
'qos_specs': {
|
||||||
|
'consumer': 'back-end',
|
||||||
|
'specs': {'upperIops': '1000'}}}
|
||||||
|
get_volume_type_qos_specs.return_value = input_qos_specs
|
||||||
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
|
FakeResponse(200, GET_LDEVS_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
||||||
ret = self.driver.manage_existing(
|
ret = self.driver.manage_existing(
|
||||||
TEST_VOLUME[0], self.test_existing_ref)
|
TEST_VOLUME[0], self.test_existing_ref)
|
||||||
self.assertEqual('1', ret['provider_location'])
|
self.assertEqual('1', ret['provider_location'])
|
||||||
self.assertEqual(2, request.call_count)
|
self.assertEqual(1, get_volume_type_qos_specs.call_count)
|
||||||
|
self.assertEqual(4, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_manage_existing_name(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_manage_existing_name(self, get_volume_type_qos_specs, request):
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEVS_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEVS_RESULT),
|
||||||
FakeResponse(200, GET_LDEV_RESULT),
|
FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
|
FakeResponse(200, GET_LDEVS_RESULT)]
|
||||||
ret = self.driver.manage_existing(
|
ret = self.driver.manage_existing(
|
||||||
TEST_VOLUME[0], self.test_existing_ref_name)
|
TEST_VOLUME[0], self.test_existing_ref_name)
|
||||||
self.assertEqual('1', ret['provider_location'])
|
self.assertEqual('1', ret['provider_location'])
|
||||||
self.assertEqual(3, request.call_count)
|
self.assertEqual(1, get_volume_type_qos_specs.call_count)
|
||||||
|
self.assertEqual(4, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_manage_existing_get_size(self, request):
|
def test_manage_existing_get_size(self, request):
|
||||||
@ -1353,10 +1456,13 @@ class HBSDRESTFCDriverTest(test.TestCase):
|
|||||||
TEST_SNAPSHOT[0])
|
TEST_SNAPSHOT[0])
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_retype(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_retype(self, get_volume_type_qos_specs, request):
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(200, GET_LDEV_RESULT),
|
FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
|
FakeResponse(200, GET_LDEVS_RESULT)]
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
host = {
|
host = {
|
||||||
'capabilities': {
|
'capabilities': {
|
||||||
'location_info': {
|
'location_info': {
|
||||||
@ -1364,8 +1470,10 @@ class HBSDRESTFCDriverTest(test.TestCase):
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
new_type = {'extra_specs': {
|
extra_specs = {'hbsd:capacity_saving': 'deduplication_compression'}
|
||||||
'hbsd:capacity_saving': 'deduplication_compression'}}
|
new_type = fake_volume.fake_volume_type_obj(
|
||||||
|
CTXT, id='00000000-0000-0000-0000-{0:012d}'.format(0),
|
||||||
|
extra_specs=extra_specs)
|
||||||
old_specs = {'hbsd:capacity_saving': 'disable'}
|
old_specs = {'hbsd:capacity_saving': 'disable'}
|
||||||
new_specs = {'hbsd:capacity_saving': 'deduplication_compression'}
|
new_specs = {'hbsd:capacity_saving': 'deduplication_compression'}
|
||||||
old_type_ref = volume_types.create(self.ctxt, 'old', old_specs)
|
old_type_ref = volume_types.create(self.ctxt, 'old', old_specs)
|
||||||
@ -1374,9 +1482,90 @@ class HBSDRESTFCDriverTest(test.TestCase):
|
|||||||
new_type_ref['id'])[0]
|
new_type_ref['id'])[0]
|
||||||
ret = self.driver.retype(
|
ret = self.driver.retype(
|
||||||
self.ctxt, TEST_VOLUME[0], new_type, diff, host)
|
self.ctxt, TEST_VOLUME[0], new_type, diff, host)
|
||||||
self.assertEqual(3, request.call_count)
|
self.assertEqual(4, request.call_count)
|
||||||
self.assertTrue(ret)
|
self.assertTrue(ret)
|
||||||
|
|
||||||
|
@mock.patch.object(requests.Session, "request")
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_retype_qos(self, get_volume_type_qos_specs, request):
|
||||||
|
input_qos_specs = {'qos_specs': {
|
||||||
|
'consumer': 'back-end',
|
||||||
|
'specs': {'upperIops': '2000'}}}
|
||||||
|
get_volume_type_qos_specs.return_value = input_qos_specs
|
||||||
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
|
FakeResponse(200, GET_LDEVS_RESULT_QOS),
|
||||||
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
||||||
|
host = {
|
||||||
|
'capabilities': {
|
||||||
|
'location_info': {
|
||||||
|
'pool_id': 30,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
qos_spec_id = '00000000-0000-0000-0000-000000000001'
|
||||||
|
new_type = fake_volume.fake_volume_type_obj(
|
||||||
|
CTXT, id='00000000-0000-0000-0000-{0:012d}'.format(0),
|
||||||
|
qos_spec_id=qos_spec_id)
|
||||||
|
diff = {'qos_specs': {'upperIops': ('1000', '2000')}}
|
||||||
|
ret = self.driver.retype(
|
||||||
|
self.ctxt, TEST_VOLUME[0], new_type, diff, host)
|
||||||
|
self.assertEqual(1, get_volume_type_qos_specs.call_count)
|
||||||
|
self.assertEqual(4, request.call_count)
|
||||||
|
self.assertTrue(ret)
|
||||||
|
|
||||||
|
@mock.patch.object(requests.Session, "request")
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_retype_migrate_qos(
|
||||||
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
|
qos_spec_id = '00000000-0000-0000-0000-000000000001'
|
||||||
|
input_qos_specs = {'qos_specs': {
|
||||||
|
'consumer': 'back-end',
|
||||||
|
'id': qos_spec_id,
|
||||||
|
'specs': {'upperIops': '2000'}}}
|
||||||
|
get_volume_type_qos_specs.return_value = input_qos_specs
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
|
||||||
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
|
FakeResponse(200, GET_LDEV_RESULT),
|
||||||
|
FakeResponse(200, GET_LDEV_RESULT),
|
||||||
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
|
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
||||||
|
FakeResponse(200, NOTFOUND_RESULT),
|
||||||
|
FakeResponse(200, NOTFOUND_RESULT),
|
||||||
|
FakeResponse(200, NOTFOUND_RESULT),
|
||||||
|
FakeResponse(200, NOTFOUND_RESULT),
|
||||||
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
|
FakeResponse(200, GET_LDEV_RESULT),
|
||||||
|
FakeResponse(200, GET_LDEV_RESULT),
|
||||||
|
FakeResponse(200, GET_LDEV_RESULT),
|
||||||
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
||||||
|
host = {
|
||||||
|
'capabilities': {
|
||||||
|
'location_info': {
|
||||||
|
'storage_id': CONFIG_MAP['serial'],
|
||||||
|
'pool_id': 30,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
extra_specs = {'hbsd:target_ports': 'CL1-A'}
|
||||||
|
new_type = fake_volume.fake_volume_type_obj(
|
||||||
|
CTXT, id='00000000-0000-0000-0000-{0:012d}'.format(0),
|
||||||
|
extra_specs=extra_specs, qos_specs_id=qos_spec_id)
|
||||||
|
diff = {'extra_specs': {'hbsd:target_ports': 'CL1-A'},
|
||||||
|
'qos_specs': {'upperIops': ('1000', '2000')},
|
||||||
|
'encryption': {}}
|
||||||
|
ret = self.driver.retype(
|
||||||
|
self.ctxt, TEST_VOLUME[0], new_type, diff, host)
|
||||||
|
self.assertEqual(1, get_volume_type_qos_specs.call_count)
|
||||||
|
self.assertEqual(16, request.call_count)
|
||||||
|
actual = (True, {'provider_location': '1'})
|
||||||
|
self.assertTupleEqual(actual, ret)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_migrate_volume(self, request):
|
def test_migrate_volume(self, request):
|
||||||
request.return_value = FakeResponse(200, GET_LDEV_RESULT)
|
request.return_value = FakeResponse(200, GET_LDEV_RESULT)
|
||||||
@ -1395,9 +1584,11 @@ class HBSDRESTFCDriverTest(test.TestCase):
|
|||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
def test_migrate_volume_diff_pool(
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
self, get_volume_type_extra_specs, request):
|
def test_migrate_volume_diff_pool(self, get_volume_type_qos_specs,
|
||||||
|
get_volume_type_extra_specs, request):
|
||||||
get_volume_type_extra_specs.return_value = {}
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(200, GET_LDEV_RESULT),
|
FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(200, GET_LDEV_RESULT),
|
FakeResponse(200, GET_LDEV_RESULT),
|
||||||
@ -1423,6 +1614,7 @@ class HBSDRESTFCDriverTest(test.TestCase):
|
|||||||
}
|
}
|
||||||
ret = self.driver.migrate_volume(self.ctxt, TEST_VOLUME[0], host)
|
ret = self.driver.migrate_volume(self.ctxt, TEST_VOLUME[0], host)
|
||||||
self.assertEqual(1, get_volume_type_extra_specs.call_count)
|
self.assertEqual(1, get_volume_type_extra_specs.call_count)
|
||||||
|
self.assertEqual(1, get_volume_type_qos_specs.call_count)
|
||||||
self.assertEqual(15, request.call_count)
|
self.assertEqual(15, request.call_count)
|
||||||
actual = (True, {'provider_location': '1'})
|
actual = (True, {'provider_location': '1'})
|
||||||
self.assertTupleEqual(actual, ret)
|
self.assertTupleEqual(actual, ret)
|
||||||
@ -1468,9 +1660,12 @@ class HBSDRESTFCDriverTest(test.TestCase):
|
|||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
def test_create_group_from_src_volume(
|
def test_create_group_from_src_volume(
|
||||||
self, get_volume_type_extra_specs, request):
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
get_volume_type_extra_specs.return_value = {}
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
@ -1484,6 +1679,7 @@ class HBSDRESTFCDriverTest(test.TestCase):
|
|||||||
source_group=TEST_GROUP[0], source_vols=[TEST_VOLUME[0]]
|
source_group=TEST_GROUP[0], source_vols=[TEST_VOLUME[0]]
|
||||||
)
|
)
|
||||||
self.assertEqual(1, get_volume_type_extra_specs.call_count)
|
self.assertEqual(1, get_volume_type_extra_specs.call_count)
|
||||||
|
self.assertEqual(1, get_volume_type_qos_specs.call_count)
|
||||||
self.assertEqual(5, request.call_count)
|
self.assertEqual(5, request.call_count)
|
||||||
actual = (
|
actual = (
|
||||||
None, [{'id': TEST_VOLUME[1]['id'], 'provider_location': '1'}])
|
None, [{'id': TEST_VOLUME[1]['id'], 'provider_location': '1'}])
|
||||||
@ -1491,9 +1687,12 @@ class HBSDRESTFCDriverTest(test.TestCase):
|
|||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
def test_create_group_from_src_snapshot(
|
def test_create_group_from_src_snapshot(
|
||||||
self, get_volume_type_extra_specs, request):
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
get_volume_type_extra_specs.return_value = {}
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
@ -1507,12 +1706,16 @@ class HBSDRESTFCDriverTest(test.TestCase):
|
|||||||
group_snapshot=TEST_GROUP_SNAP[0], snapshots=[TEST_SNAPSHOT[0]]
|
group_snapshot=TEST_GROUP_SNAP[0], snapshots=[TEST_SNAPSHOT[0]]
|
||||||
)
|
)
|
||||||
self.assertEqual(1, get_volume_type_extra_specs.call_count)
|
self.assertEqual(1, get_volume_type_extra_specs.call_count)
|
||||||
|
self.assertEqual(1, get_volume_type_qos_specs.call_count)
|
||||||
self.assertEqual(5, request.call_count)
|
self.assertEqual(5, request.call_count)
|
||||||
actual = (
|
actual = (
|
||||||
None, [{'id': TEST_VOLUME[0]['id'], 'provider_location': '1'}])
|
None, [{'id': TEST_VOLUME[0]['id'], 'provider_location': '1'}])
|
||||||
self.assertTupleEqual(actual, ret)
|
self.assertTupleEqual(actual, ret)
|
||||||
|
|
||||||
def test_create_group_from_src_volume_error(self):
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_group_from_src_volume_error(
|
||||||
|
self, get_volume_type_qos_specs):
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exception.VolumeDriverException, self.driver.create_group_from_src,
|
exception.VolumeDriverException, self.driver.create_group_from_src,
|
||||||
self.ctxt, TEST_GROUP[1], [TEST_VOLUME[1]],
|
self.ctxt, TEST_GROUP[1], [TEST_VOLUME[1]],
|
||||||
@ -1539,11 +1742,13 @@ class HBSDRESTFCDriverTest(test.TestCase):
|
|||||||
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
||||||
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
@mock.patch.object(volume_utils, 'is_group_a_cg_snapshot_type')
|
@mock.patch.object(volume_utils, 'is_group_a_cg_snapshot_type')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
def test_create_group_snapshot_non_cg(
|
def test_create_group_snapshot_non_cg(
|
||||||
self, is_group_a_cg_snapshot_type, get_volume_type_extra_specs,
|
self, get_volume_type_qos_specs, is_group_a_cg_snapshot_type,
|
||||||
volume_get, request):
|
get_volume_type_extra_specs, volume_get, request):
|
||||||
is_group_a_cg_snapshot_type.return_value = False
|
is_group_a_cg_snapshot_type.return_value = False
|
||||||
get_volume_type_extra_specs.return_value = {}
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
@ -1569,11 +1774,13 @@ class HBSDRESTFCDriverTest(test.TestCase):
|
|||||||
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
||||||
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
@mock.patch.object(volume_utils, 'is_group_a_cg_snapshot_type')
|
@mock.patch.object(volume_utils, 'is_group_a_cg_snapshot_type')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
def test_create_group_snapshot_cg(
|
def test_create_group_snapshot_cg(
|
||||||
self, is_group_a_cg_snapshot_type, get_volume_type_extra_specs,
|
self, get_volume_type_qos_specs, is_group_a_cg_snapshot_type,
|
||||||
volume_get, request):
|
get_volume_type_extra_specs, volume_get, request):
|
||||||
is_group_a_cg_snapshot_type.return_value = True
|
is_group_a_cg_snapshot_type.return_value = True
|
||||||
get_volume_type_extra_specs.return_value = {}
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
request.side_effect = [FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
request.side_effect = [FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
@ -1587,6 +1794,7 @@ class HBSDRESTFCDriverTest(test.TestCase):
|
|||||||
self.ctxt, TEST_GROUP_SNAP[0], [TEST_SNAPSHOT[0]]
|
self.ctxt, TEST_GROUP_SNAP[0], [TEST_SNAPSHOT[0]]
|
||||||
)
|
)
|
||||||
self.assertEqual(1, get_volume_type_extra_specs.call_count)
|
self.assertEqual(1, get_volume_type_extra_specs.call_count)
|
||||||
|
self.assertEqual(1, get_volume_type_qos_specs.call_count)
|
||||||
self.assertEqual(6, request.call_count)
|
self.assertEqual(6, request.call_count)
|
||||||
actual = (
|
actual = (
|
||||||
None,
|
None,
|
||||||
@ -1641,12 +1849,16 @@ class HBSDRESTFCDriverTest(test.TestCase):
|
|||||||
self.assertEqual(actual, ret)
|
self.assertEqual(actual, ret)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_is_modifiable_dr_value_new_dr_mode_disabled(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_is_modifiable_dr_value_new_dr_mode_disabled(
|
||||||
|
self, get_volume_type_qos_specs, request):
|
||||||
request.side_effect = [
|
request.side_effect = [
|
||||||
FakeResponse(200, GET_LDEV_RESULT_PAIR_STATUS_TEST),
|
FakeResponse(200, GET_LDEV_RESULT_PAIR_STATUS_TEST),
|
||||||
FakeResponse(200, GET_LDEV_RESULT_PAIR_STATUS_TEST),
|
FakeResponse(200, GET_LDEV_RESULT_PAIR_STATUS_TEST),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
|
FakeResponse(200, GET_LDEVS_RESULT),
|
||||||
]
|
]
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
host = {
|
host = {
|
||||||
'capabilities': {
|
'capabilities': {
|
||||||
'location_info': {
|
'location_info': {
|
||||||
@ -1654,7 +1866,10 @@ class HBSDRESTFCDriverTest(test.TestCase):
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
new_type = {'extra_specs': {'hbsd:capacity_saving': 'disable'}}
|
extra_specs = {'hbsd:capacity_saving': 'disable'}
|
||||||
|
new_type = fake_volume.fake_volume_type_obj(
|
||||||
|
CTXT, id='00000000-0000-0000-0000-{0:012d}'.format(0),
|
||||||
|
extra_specs=extra_specs)
|
||||||
old_specs = {'hbsd:capacity_saving': 'deduplication_compression'}
|
old_specs = {'hbsd:capacity_saving': 'deduplication_compression'}
|
||||||
new_specs = {'hbsd:capacity_saving': 'disable'}
|
new_specs = {'hbsd:capacity_saving': 'disable'}
|
||||||
old_type_ref = volume_types.create(self.ctxt, 'old', old_specs)
|
old_type_ref = volume_types.create(self.ctxt, 'old', old_specs)
|
||||||
@ -1663,5 +1878,5 @@ class HBSDRESTFCDriverTest(test.TestCase):
|
|||||||
new_type_ref['id'])[0]
|
new_type_ref['id'])[0]
|
||||||
ret = self.driver.retype(
|
ret = self.driver.retype(
|
||||||
self.ctxt, TEST_VOLUME[0], new_type, diff, host)
|
self.ctxt, TEST_VOLUME[0], new_type, diff, host)
|
||||||
self.assertEqual(3, request.call_count)
|
self.assertEqual(4, request.call_count)
|
||||||
self.assertTrue(ret)
|
self.assertTrue(ret)
|
||||||
|
@ -69,18 +69,20 @@ DEFAULT_CONNECTOR = {
|
|||||||
CTXT = cinder_context.get_admin_context()
|
CTXT = cinder_context.get_admin_context()
|
||||||
|
|
||||||
TEST_VOLUME = []
|
TEST_VOLUME = []
|
||||||
for i in range(4):
|
for i in range(5):
|
||||||
volume = {}
|
volume = {}
|
||||||
volume['id'] = '00000000-0000-0000-0000-{0:012d}'.format(i)
|
volume['id'] = '00000000-0000-0000-0000-{0:012d}'.format(i)
|
||||||
volume['name'] = 'test-volume{0:d}'.format(i)
|
volume['name'] = 'test-volume{0:d}'.format(i)
|
||||||
volume['volume_type_id'] = '00000000-0000-0000-0000-{0:012d}'.format(i)
|
volume['volume_type_id'] = '00000000-0000-0000-0000-{0:012d}'.format(i)
|
||||||
if i == 3:
|
if i == 3 or i == 4:
|
||||||
volume['provider_location'] = None
|
volume['provider_location'] = None
|
||||||
else:
|
else:
|
||||||
volume['provider_location'] = '{0:d}'.format(i)
|
volume['provider_location'] = '{0:d}'.format(i)
|
||||||
volume['size'] = 128
|
volume['size'] = 128
|
||||||
if i == 2:
|
if i == 2:
|
||||||
volume['status'] = 'in-use'
|
volume['status'] = 'in-use'
|
||||||
|
elif i == 4:
|
||||||
|
volume['status'] = None
|
||||||
else:
|
else:
|
||||||
volume['status'] = 'available'
|
volume['status'] = 'available'
|
||||||
volume = fake_volume.fake_volume_obj(CTXT, **volume)
|
volume = fake_volume.fake_volume_obj(CTXT, **volume)
|
||||||
@ -94,15 +96,19 @@ def _volume_get(context, volume_id):
|
|||||||
|
|
||||||
|
|
||||||
TEST_SNAPSHOT = []
|
TEST_SNAPSHOT = []
|
||||||
|
for i in range(2):
|
||||||
snapshot = {}
|
snapshot = {}
|
||||||
snapshot['id'] = '10000000-0000-0000-0000-{0:012d}'.format(0)
|
snapshot['id'] = '10000000-0000-0000-0000-{0:012d}'.format(i)
|
||||||
snapshot['name'] = 'TEST_SNAPSHOT{0:d}'.format(0)
|
snapshot['name'] = 'TEST_SNAPSHOT{0:d}'.format(i)
|
||||||
snapshot['provider_location'] = '{0:d}'.format(1)
|
snapshot['provider_location'] = '{0:d}'.format(i + 1)
|
||||||
snapshot['status'] = 'available'
|
snapshot['status'] = 'available'
|
||||||
snapshot['volume_id'] = '00000000-0000-0000-0000-{0:012d}'.format(0)
|
snapshot['volume_id'] = '00000000-0000-0000-0000-{0:012d}'.format(i)
|
||||||
snapshot['volume'] = _volume_get(None, snapshot['volume_id'])
|
snapshot['volume'] = _volume_get(None, snapshot['volume_id'])
|
||||||
snapshot['volume_name'] = 'test-volume{0:d}'.format(0)
|
snapshot['volume_name'] = 'test-volume{0:d}'.format(i)
|
||||||
snapshot['volume_size'] = 128
|
snapshot['volume_size'] = 128
|
||||||
|
if i == 1:
|
||||||
|
snapshot['volume_type_id'] =\
|
||||||
|
'00000000-0000-0000-0000-{0:012d}'.format(i)
|
||||||
snapshot = obj_snap.Snapshot._from_db_object(
|
snapshot = obj_snap.Snapshot._from_db_object(
|
||||||
CTXT, obj_snap.Snapshot(),
|
CTXT, obj_snap.Snapshot(),
|
||||||
fake_snapshot.fake_db_snapshot(**snapshot))
|
fake_snapshot.fake_db_snapshot(**snapshot))
|
||||||
@ -614,12 +620,17 @@ class HBSDRESTISCSIDriverTest(test.TestCase):
|
|||||||
self.assertEqual(1, get_goodness_function.call_count)
|
self.assertEqual(1, get_goodness_function.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_create_volume(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_volume(self, get_volume_type_qos_specs,
|
||||||
|
get_volume_type_extra_specs, request):
|
||||||
request.return_value = FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)
|
request.return_value = FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
self.driver.common._stats = {}
|
self.driver.common._stats = {}
|
||||||
self.driver.common._stats['pools'] = [
|
self.driver.common._stats['pools'] = [
|
||||||
{'location_info': {'pool_id': 30}}]
|
{'location_info': {'pool_id': 30}}]
|
||||||
ret = self.driver.create_volume(fake_volume.fake_volume_obj(self.ctxt))
|
ret = self.driver.create_volume(TEST_VOLUME[4])
|
||||||
self.assertEqual('1', ret['provider_location'])
|
self.assertEqual('1', ret['provider_location'])
|
||||||
self.assertEqual(2, request.call_count)
|
self.assertEqual(2, request.call_count)
|
||||||
|
|
||||||
@ -635,9 +646,12 @@ class HBSDRESTISCSIDriverTest(test.TestCase):
|
|||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
def test_create_snapshot(
|
def test_create_snapshot(
|
||||||
self, volume_get, get_volume_type_extra_specs, request):
|
self, get_volume_type_qos_specs, volume_get,
|
||||||
|
get_volume_type_extra_specs, request):
|
||||||
get_volume_type_extra_specs.return_value = {}
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
@ -649,8 +663,37 @@ class HBSDRESTISCSIDriverTest(test.TestCase):
|
|||||||
ret = self.driver.create_snapshot(TEST_SNAPSHOT[0])
|
ret = self.driver.create_snapshot(TEST_SNAPSHOT[0])
|
||||||
self.assertEqual('1', ret['provider_location'])
|
self.assertEqual('1', ret['provider_location'])
|
||||||
self.assertEqual(1, get_volume_type_extra_specs.call_count)
|
self.assertEqual(1, get_volume_type_extra_specs.call_count)
|
||||||
|
self.assertEqual(1, get_volume_type_qos_specs.call_count)
|
||||||
self.assertEqual(5, request.call_count)
|
self.assertEqual(5, request.call_count)
|
||||||
|
|
||||||
|
@mock.patch.object(requests.Session, "request")
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_snapshot_qos(
|
||||||
|
self, get_volume_type_qos_specs, volume_get,
|
||||||
|
get_volume_type_extra_specs, request):
|
||||||
|
input_qos_specs = {
|
||||||
|
'qos_specs': {
|
||||||
|
'consumer': 'back-end',
|
||||||
|
'specs': {'upperIops': '1000'}}}
|
||||||
|
get_volume_type_qos_specs.return_value = input_qos_specs
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
|
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
||||||
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
||||||
|
self.driver.common._stats = {}
|
||||||
|
self.driver.common._stats['pools'] = [
|
||||||
|
{'location_info': {'pool_id': 30}}]
|
||||||
|
ret = self.driver.create_snapshot(TEST_SNAPSHOT[1])
|
||||||
|
self.assertEqual('1', ret['provider_location'])
|
||||||
|
self.assertEqual(1, get_volume_type_extra_specs.call_count)
|
||||||
|
self.assertEqual(1, get_volume_type_qos_specs.call_count)
|
||||||
|
self.assertEqual(6, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_delete_snapshot(self, request):
|
def test_delete_snapshot(self, request):
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT_SNAP),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT_SNAP),
|
||||||
@ -668,32 +711,66 @@ class HBSDRESTISCSIDriverTest(test.TestCase):
|
|||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
def test_create_cloned_volume(
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
self, get_volume_type_extra_specs, request):
|
def test_create_cloned_volume(self, get_volume_type_qos_specs,
|
||||||
|
get_volume_type_extra_specs, request):
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
||||||
get_volume_type_extra_specs.return_value = {}
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
self.driver.common._stats = {}
|
self.driver.common._stats = {}
|
||||||
self.driver.common._stats['pools'] = [
|
self.driver.common._stats['pools'] = [
|
||||||
{'location_info': {'pool_id': 30}}]
|
{'location_info': {'pool_id': 30}}]
|
||||||
vol = self.driver.create_cloned_volume(TEST_VOLUME[0], TEST_VOLUME[1])
|
vol = self.driver.create_cloned_volume(TEST_VOLUME[0], TEST_VOLUME[1])
|
||||||
self.assertEqual('1', vol['provider_location'])
|
self.assertEqual('1', vol['provider_location'])
|
||||||
self.assertEqual(1, get_volume_type_extra_specs.call_count)
|
self.assertEqual(1, get_volume_type_extra_specs.call_count)
|
||||||
|
self.assertEqual(1, get_volume_type_qos_specs.call_count)
|
||||||
self.assertEqual(5, request.call_count)
|
self.assertEqual(5, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
def test_create_volume_from_snapshot(
|
def test_create_volume_from_snapshot(
|
||||||
self, get_volume_type_extra_specs, request):
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
||||||
get_volume_type_extra_specs.return_value = {}
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
|
self.driver.common._stats = {}
|
||||||
|
self.driver.common._stats['pools'] = [
|
||||||
|
{'location_info': {'pool_id': 30}}]
|
||||||
|
vol = self.driver.create_volume_from_snapshot(
|
||||||
|
TEST_VOLUME[0], TEST_SNAPSHOT[0])
|
||||||
|
self.assertEqual('1', vol['provider_location'])
|
||||||
|
self.assertEqual(1, get_volume_type_extra_specs.call_count)
|
||||||
|
self.assertEqual(1, get_volume_type_qos_specs.call_count)
|
||||||
|
self.assertEqual(5, request.call_count)
|
||||||
|
|
||||||
|
@mock.patch.object(requests.Session, "request")
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_volume_from_snapshot_qos(
|
||||||
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
|
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
||||||
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
||||||
|
input_qos_specs = {
|
||||||
|
'qos_specs': {
|
||||||
|
'consumer': 'back-end',
|
||||||
|
'specs': {'upperIops': '1000'}}}
|
||||||
|
get_volume_type_qos_specs.return_value = input_qos_specs
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
self.driver.common._stats = {}
|
self.driver.common._stats = {}
|
||||||
self.driver.common._stats['pools'] = [
|
self.driver.common._stats['pools'] = [
|
||||||
{'location_info': {'pool_id': 30}}]
|
{'location_info': {'pool_id': 30}}]
|
||||||
@ -701,7 +778,8 @@ class HBSDRESTISCSIDriverTest(test.TestCase):
|
|||||||
TEST_VOLUME[0], TEST_SNAPSHOT[0])
|
TEST_VOLUME[0], TEST_SNAPSHOT[0])
|
||||||
self.assertEqual('1', vol['provider_location'])
|
self.assertEqual('1', vol['provider_location'])
|
||||||
self.assertEqual(1, get_volume_type_extra_specs.call_count)
|
self.assertEqual(1, get_volume_type_extra_specs.call_count)
|
||||||
self.assertEqual(5, request.call_count)
|
self.assertEqual(1, get_volume_type_qos_specs.call_count)
|
||||||
|
self.assertEqual(6, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
@ -823,23 +901,31 @@ class HBSDRESTISCSIDriverTest(test.TestCase):
|
|||||||
self.assertEqual(6, request.call_count)
|
self.assertEqual(6, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_manage_existing(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_manage_existing(self, get_volume_type_qos_specs, request):
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
|
FakeResponse(200, GET_LDEVS_RESULT)]
|
||||||
ret = self.driver.manage_existing(
|
ret = self.driver.manage_existing(
|
||||||
TEST_VOLUME[0], self.test_existing_ref)
|
TEST_VOLUME[0], self.test_existing_ref)
|
||||||
self.assertEqual('1', ret['provider_location'])
|
self.assertEqual('1', ret['provider_location'])
|
||||||
self.assertEqual(2, request.call_count)
|
self.assertEqual(1, get_volume_type_qos_specs.call_count)
|
||||||
|
self.assertEqual(3, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_manage_existing_name(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_manage_existing_name(self, get_volume_type_qos_specs, request):
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEVS_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEVS_RESULT),
|
||||||
FakeResponse(200, GET_LDEV_RESULT),
|
FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
|
FakeResponse(200, GET_LDEVS_RESULT)]
|
||||||
ret = self.driver.manage_existing(
|
ret = self.driver.manage_existing(
|
||||||
TEST_VOLUME[0], self.test_existing_ref_name)
|
TEST_VOLUME[0], self.test_existing_ref_name)
|
||||||
self.assertEqual('1', ret['provider_location'])
|
self.assertEqual('1', ret['provider_location'])
|
||||||
self.assertEqual(3, request.call_count)
|
self.assertEqual(1, get_volume_type_qos_specs.call_count)
|
||||||
|
self.assertEqual(4, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_manage_existing_get_size(self, request):
|
def test_manage_existing_get_size(self, request):
|
||||||
@ -895,10 +981,12 @@ class HBSDRESTISCSIDriverTest(test.TestCase):
|
|||||||
TEST_SNAPSHOT[0])
|
TEST_SNAPSHOT[0])
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_retype(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_retype(self, get_volume_type_qos_specs, request):
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(200, GET_LDEV_RESULT),
|
FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
|
FakeResponse(200, GET_LDEVS_RESULT)]
|
||||||
host = {
|
host = {
|
||||||
'capabilities': {
|
'capabilities': {
|
||||||
'location_info': {
|
'location_info': {
|
||||||
@ -906,8 +994,10 @@ class HBSDRESTISCSIDriverTest(test.TestCase):
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
new_type = {'extra_specs': {
|
extra_specs = {'hbsd:capacity_saving': 'deduplication_compression'}
|
||||||
'hbsd:capacity_saving': 'deduplication_compression'}}
|
new_type = fake_volume.fake_volume_type_obj(
|
||||||
|
CTXT, id='00000000-0000-0000-0000-{0:012d}'.format(0),
|
||||||
|
extra_specs=extra_specs)
|
||||||
old_specs = {'hbsd:capacity_saving': 'disable'}
|
old_specs = {'hbsd:capacity_saving': 'disable'}
|
||||||
new_specs = {'hbsd:capacity_saving': 'deduplication_compression'}
|
new_specs = {'hbsd:capacity_saving': 'deduplication_compression'}
|
||||||
old_type_ref = volume_types.create(self.ctxt, 'old', old_specs)
|
old_type_ref = volume_types.create(self.ctxt, 'old', old_specs)
|
||||||
@ -916,7 +1006,7 @@ class HBSDRESTISCSIDriverTest(test.TestCase):
|
|||||||
new_type_ref['id'])[0]
|
new_type_ref['id'])[0]
|
||||||
ret = self.driver.retype(
|
ret = self.driver.retype(
|
||||||
self.ctxt, TEST_VOLUME[0], new_type, diff, host)
|
self.ctxt, TEST_VOLUME[0], new_type, diff, host)
|
||||||
self.assertEqual(3, request.call_count)
|
self.assertEqual(4, request.call_count)
|
||||||
self.assertTrue(ret)
|
self.assertTrue(ret)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@ -970,9 +1060,12 @@ class HBSDRESTISCSIDriverTest(test.TestCase):
|
|||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
def test_create_group_from_src_volume(
|
def test_create_group_from_src_volume(
|
||||||
self, get_volume_type_extra_specs, request):
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
get_volume_type_extra_specs.return_value = {}
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
@ -986,6 +1079,7 @@ class HBSDRESTISCSIDriverTest(test.TestCase):
|
|||||||
source_group=TEST_GROUP[0], source_vols=[TEST_VOLUME[0]]
|
source_group=TEST_GROUP[0], source_vols=[TEST_VOLUME[0]]
|
||||||
)
|
)
|
||||||
self.assertEqual(1, get_volume_type_extra_specs.call_count)
|
self.assertEqual(1, get_volume_type_extra_specs.call_count)
|
||||||
|
self.assertEqual(1, get_volume_type_qos_specs.call_count)
|
||||||
self.assertEqual(5, request.call_count)
|
self.assertEqual(5, request.call_count)
|
||||||
actual = (
|
actual = (
|
||||||
None, [{'id': TEST_VOLUME[1]['id'], 'provider_location': '1'}])
|
None, [{'id': TEST_VOLUME[1]['id'], 'provider_location': '1'}])
|
||||||
@ -993,9 +1087,12 @@ class HBSDRESTISCSIDriverTest(test.TestCase):
|
|||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
def test_create_group_from_src_snapshot(
|
def test_create_group_from_src_snapshot(
|
||||||
self, get_volume_type_extra_specs, request):
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
get_volume_type_extra_specs.return_value = {}
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
@ -1009,11 +1106,44 @@ class HBSDRESTISCSIDriverTest(test.TestCase):
|
|||||||
group_snapshot=TEST_GROUP_SNAP[0], snapshots=[TEST_SNAPSHOT[0]]
|
group_snapshot=TEST_GROUP_SNAP[0], snapshots=[TEST_SNAPSHOT[0]]
|
||||||
)
|
)
|
||||||
self.assertEqual(1, get_volume_type_extra_specs.call_count)
|
self.assertEqual(1, get_volume_type_extra_specs.call_count)
|
||||||
|
self.assertEqual(1, get_volume_type_qos_specs.call_count)
|
||||||
self.assertEqual(5, request.call_count)
|
self.assertEqual(5, request.call_count)
|
||||||
actual = (
|
actual = (
|
||||||
None, [{'id': TEST_VOLUME[0]['id'], 'provider_location': '1'}])
|
None, [{'id': TEST_VOLUME[0]['id'], 'provider_location': '1'}])
|
||||||
self.assertTupleEqual(actual, ret)
|
self.assertTupleEqual(actual, ret)
|
||||||
|
|
||||||
|
@mock.patch.object(requests.Session, "request")
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_group_from_src_snapshot_qos(
|
||||||
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
|
input_qos_specs = {
|
||||||
|
'qos_specs': {
|
||||||
|
'consumer': 'back-end',
|
||||||
|
'specs': {'upperIops': '1000'}}}
|
||||||
|
get_volume_type_qos_specs.return_value = input_qos_specs
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
|
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
||||||
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
||||||
|
self.driver.common._stats = {}
|
||||||
|
self.driver.common._stats['pools'] = [
|
||||||
|
{'location_info': {'pool_id': 30}}]
|
||||||
|
ret = self.driver.create_group_from_src(
|
||||||
|
self.ctxt, TEST_GROUP[0], [TEST_VOLUME[0]],
|
||||||
|
group_snapshot=TEST_GROUP_SNAP[0], snapshots=[TEST_SNAPSHOT[1]]
|
||||||
|
)
|
||||||
|
self.assertEqual(1, get_volume_type_extra_specs.call_count)
|
||||||
|
self.assertEqual(1, get_volume_type_qos_specs.call_count)
|
||||||
|
self.assertEqual(6, request.call_count)
|
||||||
|
actual = (
|
||||||
|
None, [{'id': TEST_VOLUME[0]['id'], 'provider_location': '1'}])
|
||||||
|
self.assertTupleEqual(actual, ret)
|
||||||
|
|
||||||
def test_create_group_from_src_volume_error(self):
|
def test_create_group_from_src_volume_error(self):
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exception.VolumeDriverException, self.driver.create_group_from_src,
|
exception.VolumeDriverException, self.driver.create_group_from_src,
|
||||||
@ -1041,11 +1171,13 @@ class HBSDRESTISCSIDriverTest(test.TestCase):
|
|||||||
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
||||||
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
@mock.patch.object(volume_utils, 'is_group_a_cg_snapshot_type')
|
@mock.patch.object(volume_utils, 'is_group_a_cg_snapshot_type')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
def test_create_group_snapshot_non_cg(
|
def test_create_group_snapshot_non_cg(
|
||||||
self, is_group_a_cg_snapshot_type, get_volume_type_extra_specs,
|
self, get_volume_type_qos_specs, is_group_a_cg_snapshot_type,
|
||||||
volume_get, request):
|
get_volume_type_extra_specs, volume_get, request):
|
||||||
is_group_a_cg_snapshot_type.return_value = False
|
is_group_a_cg_snapshot_type.return_value = False
|
||||||
get_volume_type_extra_specs.return_value = {}
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
@ -1071,11 +1203,13 @@ class HBSDRESTISCSIDriverTest(test.TestCase):
|
|||||||
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
||||||
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
@mock.patch.object(volume_utils, 'is_group_a_cg_snapshot_type')
|
@mock.patch.object(volume_utils, 'is_group_a_cg_snapshot_type')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
def test_create_group_snapshot_cg(
|
def test_create_group_snapshot_cg(
|
||||||
self, is_group_a_cg_snapshot_type, get_volume_type_extra_specs,
|
self, get_volume_type_qos_specs, is_group_a_cg_snapshot_type,
|
||||||
volume_get, request):
|
get_volume_type_extra_specs, volume_get, request):
|
||||||
is_group_a_cg_snapshot_type.return_value = True
|
is_group_a_cg_snapshot_type.return_value = True
|
||||||
get_volume_type_extra_specs.return_value = {}
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
request.side_effect = [FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
request.side_effect = [FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
|
@ -76,20 +76,24 @@ DEFAULT_CONNECTOR = {
|
|||||||
CTXT = cinder_context.get_admin_context()
|
CTXT = cinder_context.get_admin_context()
|
||||||
|
|
||||||
TEST_VOLUME = []
|
TEST_VOLUME = []
|
||||||
for i in range(4):
|
for i in range(5):
|
||||||
volume = {}
|
volume = {}
|
||||||
volume['id'] = '00000000-0000-0000-0000-{0:012d}'.format(i)
|
volume['id'] = '00000000-0000-0000-0000-{0:012d}'.format(i)
|
||||||
volume['name'] = 'test-volume{0:d}'.format(i)
|
volume['name'] = 'test-volume{0:d}'.format(i)
|
||||||
if i == 3:
|
volume['volume_type_id'] = '00000000-0000-0000-0000-{0:012d}'.format(i)
|
||||||
|
if i == 3 or i == 4:
|
||||||
volume['provider_location'] = None
|
volume['provider_location'] = None
|
||||||
else:
|
else:
|
||||||
volume['provider_location'] = '{0:d}'.format(i)
|
volume['provider_location'] = '{0:d}'.format(i)
|
||||||
volume['size'] = 128
|
volume['size'] = 128
|
||||||
if i == 2:
|
if i == 2:
|
||||||
volume['status'] = 'in-use'
|
volume['status'] = 'in-use'
|
||||||
|
elif i == 4:
|
||||||
|
volume['status'] = None
|
||||||
else:
|
else:
|
||||||
volume['status'] = 'available'
|
volume['status'] = 'available'
|
||||||
volume = fake_volume.fake_volume_obj(CTXT, **volume)
|
volume = fake_volume.fake_volume_obj(CTXT, **volume)
|
||||||
|
volume.volume_type = fake_volume.fake_volume_type_obj(CTXT)
|
||||||
TEST_VOLUME.append(volume)
|
TEST_VOLUME.append(volume)
|
||||||
|
|
||||||
|
|
||||||
@ -633,18 +637,30 @@ class HPEXPRESTFCDriverTest(test.TestCase):
|
|||||||
self.driver.common.client.keep_session_loop.wait()
|
self.driver.common.client.keep_session_loop.wait()
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_create_volume(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_volume(
|
||||||
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
request.return_value = FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)
|
request.return_value = FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
self.driver.common._stats = {}
|
self.driver.common._stats = {}
|
||||||
self.driver.common._stats['pools'] = [
|
self.driver.common._stats['pools'] = [
|
||||||
{'location_info': {'pool_id': 30}}]
|
{'location_info': {'pool_id': 30}}]
|
||||||
ret = self.driver.create_volume(fake_volume.fake_volume_obj(self.ctxt))
|
ret = self.driver.create_volume(TEST_VOLUME[4])
|
||||||
self.assertEqual('1', ret['provider_location'])
|
self.assertEqual('1', ret['provider_location'])
|
||||||
self.assertEqual(2, request.call_count)
|
self.assertEqual(2, request.call_count)
|
||||||
|
|
||||||
@reduce_retrying_time
|
@reduce_retrying_time
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_create_volume_timeout(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_volume_timeout(
|
||||||
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
request.return_value = FakeResponse(
|
request.return_value = FakeResponse(
|
||||||
500, ERROR_RESULT,
|
500, ERROR_RESULT,
|
||||||
headers={'Content-Type': 'json'})
|
headers={'Content-Type': 'json'})
|
||||||
@ -653,7 +669,7 @@ class HPEXPRESTFCDriverTest(test.TestCase):
|
|||||||
{'location_info': {'pool_id': 30}}]
|
{'location_info': {'pool_id': 30}}]
|
||||||
self.assertRaises(exception.VolumeDriverException,
|
self.assertRaises(exception.VolumeDriverException,
|
||||||
self.driver.create_volume,
|
self.driver.create_volume,
|
||||||
fake_volume.fake_volume_obj(self.ctxt))
|
TEST_VOLUME[4])
|
||||||
self.assertGreater(request.call_count, 1)
|
self.assertGreater(request.call_count, 1)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@ -716,12 +732,18 @@ class HPEXPRESTFCDriverTest(test.TestCase):
|
|||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
||||||
def test_create_snapshot(self, volume_get, request):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_snapshot(
|
||||||
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
volume_get, request):
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
self.driver.common._stats = {}
|
self.driver.common._stats = {}
|
||||||
self.driver.common._stats['pools'] = [
|
self.driver.common._stats['pools'] = [
|
||||||
{'location_info': {'pool_id': 30}}]
|
{'location_info': {'pool_id': 30}}]
|
||||||
@ -755,12 +777,18 @@ class HPEXPRESTFCDriverTest(test.TestCase):
|
|||||||
self.assertEqual(4, request.call_count)
|
self.assertEqual(4, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_create_cloned_volume(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_cloned_volume(
|
||||||
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
self.driver.common._stats = {}
|
self.driver.common._stats = {}
|
||||||
self.driver.common._stats['pools'] = [
|
self.driver.common._stats['pools'] = [
|
||||||
{'location_info': {'pool_id': 30}}]
|
{'location_info': {'pool_id': 30}}]
|
||||||
@ -769,12 +797,18 @@ class HPEXPRESTFCDriverTest(test.TestCase):
|
|||||||
self.assertEqual(5, request.call_count)
|
self.assertEqual(5, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_create_volume_from_snapshot(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_volume_from_snapshot(
|
||||||
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
self.driver.common._stats = {}
|
self.driver.common._stats = {}
|
||||||
self.driver.common._stats['pools'] = [
|
self.driver.common._stats['pools'] = [
|
||||||
{'location_info': {'pool_id': 30}}]
|
{'location_info': {'pool_id': 30}}]
|
||||||
@ -785,7 +819,10 @@ class HPEXPRESTFCDriverTest(test.TestCase):
|
|||||||
|
|
||||||
@mock.patch.object(fczm_utils, "add_fc_zone")
|
@mock.patch.object(fczm_utils, "add_fc_zone")
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_initialize_connection(self, request, add_fc_zone):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
def test_initialize_connection(
|
||||||
|
self, get_volume_type_extra_specs, request, add_fc_zone):
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
self.driver.common.conf.hitachi_zoning_request = True
|
self.driver.common.conf.hitachi_zoning_request = True
|
||||||
self.driver.common._lookup_service = FakeLookupService()
|
self.driver.common._lookup_service = FakeLookupService()
|
||||||
request.side_effect = [FakeResponse(200, GET_HOST_WWNS_RESULT),
|
request.side_effect = [FakeResponse(200, GET_HOST_WWNS_RESULT),
|
||||||
@ -800,8 +837,11 @@ class HPEXPRESTFCDriverTest(test.TestCase):
|
|||||||
|
|
||||||
@mock.patch.object(fczm_utils, "add_fc_zone")
|
@mock.patch.object(fczm_utils, "add_fc_zone")
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_initialize_connection_already_mapped(self, request, add_fc_zone):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
def test_initialize_connection_already_mapped(
|
||||||
|
self, get_volume_type_extra_specs, request, add_fc_zone):
|
||||||
"""Normal case: ldev have already mapped."""
|
"""Normal case: ldev have already mapped."""
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
self.driver.common.conf.hitachi_zoning_request = True
|
self.driver.common.conf.hitachi_zoning_request = True
|
||||||
self.driver.common._lookup_service = FakeLookupService()
|
self.driver.common._lookup_service = FakeLookupService()
|
||||||
request.side_effect = [
|
request.side_effect = [
|
||||||
@ -819,9 +859,12 @@ class HPEXPRESTFCDriverTest(test.TestCase):
|
|||||||
|
|
||||||
@mock.patch.object(fczm_utils, "add_fc_zone")
|
@mock.patch.object(fczm_utils, "add_fc_zone")
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_initialize_connection_shared_target(self, request, add_fc_zone):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
def test_initialize_connection_shared_target(
|
||||||
|
self, get_volume_type_extra_specs, request, add_fc_zone):
|
||||||
"""Normal case: A target shared with other systems."""
|
"""Normal case: A target shared with other systems."""
|
||||||
self.driver.common.conf.hitachi_zoning_request = True
|
self.driver.common.conf.hitachi_zoning_request = True
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
self.driver.common._lookup_service = FakeLookupService()
|
self.driver.common._lookup_service = FakeLookupService()
|
||||||
request.side_effect = [FakeResponse(200, NOTFOUND_RESULT),
|
request.side_effect = [FakeResponse(200, NOTFOUND_RESULT),
|
||||||
FakeResponse(200, NOTFOUND_RESULT),
|
FakeResponse(200, NOTFOUND_RESULT),
|
||||||
@ -911,23 +954,29 @@ class HPEXPRESTFCDriverTest(test.TestCase):
|
|||||||
self.assertEqual(1, remove_fc_zone.call_count)
|
self.assertEqual(1, remove_fc_zone.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_manage_existing(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_manage_existing(self, get_volume_type_qos_specs, request):
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
|
FakeResponse(200, GET_LDEVS_RESULT)]
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
ret = self.driver.manage_existing(
|
ret = self.driver.manage_existing(
|
||||||
TEST_VOLUME[0], self.test_existing_ref)
|
TEST_VOLUME[0], self.test_existing_ref)
|
||||||
self.assertEqual('1', ret['provider_location'])
|
self.assertEqual('1', ret['provider_location'])
|
||||||
self.assertEqual(2, request.call_count)
|
self.assertEqual(3, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_manage_existing_name(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_manage_existing_name(self, get_volume_type_qos_specs, request):
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEVS_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEVS_RESULT),
|
||||||
FakeResponse(200, GET_LDEV_RESULT),
|
FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
|
FakeResponse(200, GET_LDEVS_RESULT)]
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
ret = self.driver.manage_existing(
|
ret = self.driver.manage_existing(
|
||||||
TEST_VOLUME[0], self.test_existing_ref_name)
|
TEST_VOLUME[0], self.test_existing_ref_name)
|
||||||
self.assertEqual('1', ret['provider_location'])
|
self.assertEqual('1', ret['provider_location'])
|
||||||
self.assertEqual(3, request.call_count)
|
self.assertEqual(4, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_manage_existing_get_size(self, request):
|
def test_manage_existing_get_size(self, request):
|
||||||
@ -1041,12 +1090,18 @@ class HPEXPRESTFCDriverTest(test.TestCase):
|
|||||||
self.assertTupleEqual(actual, ret)
|
self.assertTupleEqual(actual, ret)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_create_group_from_src_volume(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_group_from_src_volume(
|
||||||
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
self.driver.common._stats = {}
|
self.driver.common._stats = {}
|
||||||
self.driver.common._stats['pools'] = [
|
self.driver.common._stats['pools'] = [
|
||||||
{'location_info': {'pool_id': 30}}]
|
{'location_info': {'pool_id': 30}}]
|
||||||
@ -1060,12 +1115,18 @@ class HPEXPRESTFCDriverTest(test.TestCase):
|
|||||||
self.assertTupleEqual(actual, ret)
|
self.assertTupleEqual(actual, ret)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_create_group_from_src_snapshot(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_group_from_src_snapshot(
|
||||||
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
self.driver.common._stats = {}
|
self.driver.common._stats = {}
|
||||||
self.driver.common._stats['pools'] = [
|
self.driver.common._stats['pools'] = [
|
||||||
{'location_info': {'pool_id': 30}}]
|
{'location_info': {'pool_id': 30}}]
|
||||||
@ -1078,7 +1139,10 @@ class HPEXPRESTFCDriverTest(test.TestCase):
|
|||||||
None, [{'id': TEST_VOLUME[0]['id'], 'provider_location': '1'}])
|
None, [{'id': TEST_VOLUME[0]['id'], 'provider_location': '1'}])
|
||||||
self.assertTupleEqual(actual, ret)
|
self.assertTupleEqual(actual, ret)
|
||||||
|
|
||||||
def test_create_group_from_src_volume_error(self):
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_group_from_src_volume_error(
|
||||||
|
self, get_volume_type_qos_specs):
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exception.VolumeDriverException, self.driver.create_group_from_src,
|
exception.VolumeDriverException, self.driver.create_group_from_src,
|
||||||
self.ctxt, TEST_GROUP[1], [TEST_VOLUME[1]],
|
self.ctxt, TEST_GROUP[1], [TEST_VOLUME[1]],
|
||||||
@ -1104,9 +1168,14 @@ class HPEXPRESTFCDriverTest(test.TestCase):
|
|||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
||||||
@mock.patch.object(volume_utils, 'is_group_a_cg_snapshot_type')
|
@mock.patch.object(volume_utils, 'is_group_a_cg_snapshot_type')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
def test_create_group_snapshot_non_cg(
|
def test_create_group_snapshot_non_cg(
|
||||||
self, is_group_a_cg_snapshot_type, volume_get, request):
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
is_group_a_cg_snapshot_type, volume_get, request):
|
||||||
is_group_a_cg_snapshot_type.return_value = False
|
is_group_a_cg_snapshot_type.return_value = False
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
@ -1130,9 +1199,14 @@ class HPEXPRESTFCDriverTest(test.TestCase):
|
|||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
||||||
@mock.patch.object(volume_utils, 'is_group_a_cg_snapshot_type')
|
@mock.patch.object(volume_utils, 'is_group_a_cg_snapshot_type')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
def test_create_group_snapshot_cg(
|
def test_create_group_snapshot_cg(
|
||||||
self, is_group_a_cg_snapshot_type, volume_get, request):
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
is_group_a_cg_snapshot_type, volume_get, request):
|
||||||
is_group_a_cg_snapshot_type.return_value = True
|
is_group_a_cg_snapshot_type.return_value = True
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
request.side_effect = [FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
request.side_effect = [FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
|
@ -69,20 +69,24 @@ DEFAULT_CONNECTOR = {
|
|||||||
CTXT = cinder_context.get_admin_context()
|
CTXT = cinder_context.get_admin_context()
|
||||||
|
|
||||||
TEST_VOLUME = []
|
TEST_VOLUME = []
|
||||||
for i in range(4):
|
for i in range(5):
|
||||||
volume = {}
|
volume = {}
|
||||||
volume['id'] = '00000000-0000-0000-0000-{0:012d}'.format(i)
|
volume['id'] = '00000000-0000-0000-0000-{0:012d}'.format(i)
|
||||||
volume['name'] = 'test-volume{0:d}'.format(i)
|
volume['name'] = 'test-volume{0:d}'.format(i)
|
||||||
if i == 3:
|
volume['volume_type_id'] = '00000000-0000-0000-0000-{0:012d}'.format(i)
|
||||||
|
if i == 3 or i == 4:
|
||||||
volume['provider_location'] = None
|
volume['provider_location'] = None
|
||||||
else:
|
else:
|
||||||
volume['provider_location'] = '{0:d}'.format(i)
|
volume['provider_location'] = '{0:d}'.format(i)
|
||||||
volume['size'] = 128
|
volume['size'] = 128
|
||||||
if i == 2:
|
if i == 2:
|
||||||
volume['status'] = 'in-use'
|
volume['status'] = 'in-use'
|
||||||
|
elif i == 4:
|
||||||
|
volume['status'] = None
|
||||||
else:
|
else:
|
||||||
volume['status'] = 'available'
|
volume['status'] = 'available'
|
||||||
volume = fake_volume.fake_volume_obj(CTXT, **volume)
|
volume = fake_volume.fake_volume_obj(CTXT, **volume)
|
||||||
|
volume.volume_type = fake_volume.fake_volume_type_obj(CTXT)
|
||||||
TEST_VOLUME.append(volume)
|
TEST_VOLUME.append(volume)
|
||||||
|
|
||||||
|
|
||||||
@ -535,12 +539,18 @@ class HPEXPRESTISCSIDriverTest(test.TestCase):
|
|||||||
self.assertEqual(1, get_goodness_function.call_count)
|
self.assertEqual(1, get_goodness_function.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_create_volume(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_volume(
|
||||||
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
request.return_value = FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)
|
request.return_value = FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
self.driver.common._stats = {}
|
self.driver.common._stats = {}
|
||||||
self.driver.common._stats['pools'] = [
|
self.driver.common._stats['pools'] = [
|
||||||
{'location_info': {'pool_id': 30}}]
|
{'location_info': {'pool_id': 30}}]
|
||||||
ret = self.driver.create_volume(fake_volume.fake_volume_obj(self.ctxt))
|
ret = self.driver.create_volume(TEST_VOLUME[4])
|
||||||
self.assertEqual('1', ret['provider_location'])
|
self.assertEqual('1', ret['provider_location'])
|
||||||
self.assertEqual(2, request.call_count)
|
self.assertEqual(2, request.call_count)
|
||||||
|
|
||||||
@ -555,12 +565,18 @@ class HPEXPRESTISCSIDriverTest(test.TestCase):
|
|||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
||||||
def test_create_snapshot(self, volume_get, request):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_snapshot(
|
||||||
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
volume_get, request):
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
self.driver.common._stats = {}
|
self.driver.common._stats = {}
|
||||||
self.driver.common._stats['pools'] = [
|
self.driver.common._stats['pools'] = [
|
||||||
{'location_info': {'pool_id': 30}}]
|
{'location_info': {'pool_id': 30}}]
|
||||||
@ -578,12 +594,18 @@ class HPEXPRESTISCSIDriverTest(test.TestCase):
|
|||||||
self.assertEqual(4, request.call_count)
|
self.assertEqual(4, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_create_cloned_volume(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_cloned_volume(
|
||||||
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
self.driver.common._stats = {}
|
self.driver.common._stats = {}
|
||||||
self.driver.common._stats['pools'] = [
|
self.driver.common._stats['pools'] = [
|
||||||
{'location_info': {'pool_id': 30}}]
|
{'location_info': {'pool_id': 30}}]
|
||||||
@ -592,12 +614,18 @@ class HPEXPRESTISCSIDriverTest(test.TestCase):
|
|||||||
self.assertEqual(5, request.call_count)
|
self.assertEqual(5, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_create_volume_from_snapshot(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_volume_from_snapshot(
|
||||||
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
self.driver.common._stats = {}
|
self.driver.common._stats = {}
|
||||||
self.driver.common._stats['pools'] = [
|
self.driver.common._stats['pools'] = [
|
||||||
{'location_info': {'pool_id': 30}}]
|
{'location_info': {'pool_id': 30}}]
|
||||||
@ -607,7 +635,10 @@ class HPEXPRESTISCSIDriverTest(test.TestCase):
|
|||||||
self.assertEqual(5, request.call_count)
|
self.assertEqual(5, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_initialize_connection(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
def test_initialize_connection(
|
||||||
|
self, get_volume_type_extra_specs, request):
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
request.side_effect = [FakeResponse(200, GET_HOST_ISCSIS_RESULT),
|
request.side_effect = [FakeResponse(200, GET_HOST_ISCSIS_RESULT),
|
||||||
FakeResponse(200, GET_HOST_GROUP_RESULT),
|
FakeResponse(200, GET_HOST_GROUP_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
||||||
@ -630,8 +661,11 @@ class HPEXPRESTISCSIDriverTest(test.TestCase):
|
|||||||
self.assertEqual(3, request.call_count)
|
self.assertEqual(3, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_initialize_connection_shared_target(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
def test_initialize_connection_shared_target(
|
||||||
|
self, get_volume_type_extra_specs, request):
|
||||||
"""Normal case: A target shared with other systems."""
|
"""Normal case: A target shared with other systems."""
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
request.side_effect = [FakeResponse(200, NOTFOUND_RESULT),
|
request.side_effect = [FakeResponse(200, NOTFOUND_RESULT),
|
||||||
FakeResponse(200, GET_HOST_GROUPS_RESULT),
|
FakeResponse(200, GET_HOST_GROUPS_RESULT),
|
||||||
FakeResponse(200, GET_HOST_ISCSIS_RESULT),
|
FakeResponse(200, GET_HOST_ISCSIS_RESULT),
|
||||||
@ -716,23 +750,29 @@ class HPEXPRESTISCSIDriverTest(test.TestCase):
|
|||||||
self.assertEqual(6, request.call_count)
|
self.assertEqual(6, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_manage_existing(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_manage_existing(self, get_volume_type_qos_specs, request):
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
|
FakeResponse(200, GET_LDEVS_RESULT)]
|
||||||
ret = self.driver.manage_existing(
|
ret = self.driver.manage_existing(
|
||||||
TEST_VOLUME[0], self.test_existing_ref)
|
TEST_VOLUME[0], self.test_existing_ref)
|
||||||
self.assertEqual('1', ret['provider_location'])
|
self.assertEqual('1', ret['provider_location'])
|
||||||
self.assertEqual(2, request.call_count)
|
self.assertEqual(3, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_manage_existing_name(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_manage_existing_name(self, get_volume_type_qos_specs, request):
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEVS_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEVS_RESULT),
|
||||||
FakeResponse(200, GET_LDEV_RESULT),
|
FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
|
FakeResponse(200, GET_LDEVS_RESULT)]
|
||||||
ret = self.driver.manage_existing(
|
ret = self.driver.manage_existing(
|
||||||
TEST_VOLUME[0], self.test_existing_ref_name)
|
TEST_VOLUME[0], self.test_existing_ref_name)
|
||||||
self.assertEqual('1', ret['provider_location'])
|
self.assertEqual('1', ret['provider_location'])
|
||||||
self.assertEqual(3, request.call_count)
|
self.assertEqual(4, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_manage_existing_get_size(self, request):
|
def test_manage_existing_get_size(self, request):
|
||||||
@ -840,12 +880,18 @@ class HPEXPRESTISCSIDriverTest(test.TestCase):
|
|||||||
self.assertTupleEqual(actual, ret)
|
self.assertTupleEqual(actual, ret)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_create_group_from_src_volume(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_group_from_src_volume(
|
||||||
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
self.driver.common._stats = {}
|
self.driver.common._stats = {}
|
||||||
self.driver.common._stats['pools'] = [
|
self.driver.common._stats['pools'] = [
|
||||||
{'location_info': {'pool_id': 30}}]
|
{'location_info': {'pool_id': 30}}]
|
||||||
@ -859,12 +905,18 @@ class HPEXPRESTISCSIDriverTest(test.TestCase):
|
|||||||
self.assertTupleEqual(actual, ret)
|
self.assertTupleEqual(actual, ret)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_create_group_from_src_snapshot(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_group_from_src_snapshot(
|
||||||
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
self.driver.common._stats = {}
|
self.driver.common._stats = {}
|
||||||
self.driver.common._stats['pools'] = [
|
self.driver.common._stats['pools'] = [
|
||||||
{'location_info': {'pool_id': 30}}]
|
{'location_info': {'pool_id': 30}}]
|
||||||
@ -903,9 +955,14 @@ class HPEXPRESTISCSIDriverTest(test.TestCase):
|
|||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
||||||
@mock.patch.object(volume_utils, 'is_group_a_cg_snapshot_type')
|
@mock.patch.object(volume_utils, 'is_group_a_cg_snapshot_type')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
def test_create_group_snapshot_non_cg(
|
def test_create_group_snapshot_non_cg(
|
||||||
self, is_group_a_cg_snapshot_type, volume_get, request):
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
is_group_a_cg_snapshot_type, volume_get, request):
|
||||||
is_group_a_cg_snapshot_type.return_value = False
|
is_group_a_cg_snapshot_type.return_value = False
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
@ -929,9 +986,15 @@ class HPEXPRESTISCSIDriverTest(test.TestCase):
|
|||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
||||||
@mock.patch.object(volume_utils, 'is_group_a_cg_snapshot_type')
|
@mock.patch.object(volume_utils, 'is_group_a_cg_snapshot_type')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
def test_create_group_snapshot_cg(
|
def test_create_group_snapshot_cg(
|
||||||
self, is_group_a_cg_snapshot_type, volume_get, request):
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
is_group_a_cg_snapshot_type,
|
||||||
|
volume_get, request):
|
||||||
is_group_a_cg_snapshot_type.return_value = True
|
is_group_a_cg_snapshot_type.return_value = True
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
request.side_effect = [FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
request.side_effect = [FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
|
@ -76,20 +76,24 @@ DEFAULT_CONNECTOR = {
|
|||||||
CTXT = cinder_context.get_admin_context()
|
CTXT = cinder_context.get_admin_context()
|
||||||
|
|
||||||
TEST_VOLUME = []
|
TEST_VOLUME = []
|
||||||
for i in range(4):
|
for i in range(5):
|
||||||
volume = {}
|
volume = {}
|
||||||
volume['id'] = '00000000-0000-0000-0000-{0:012d}'.format(i)
|
volume['id'] = '00000000-0000-0000-0000-{0:012d}'.format(i)
|
||||||
volume['name'] = 'test-volume{0:d}'.format(i)
|
volume['name'] = 'test-volume{0:d}'.format(i)
|
||||||
if i == 3:
|
volume['volume_type_id'] = '00000000-0000-0000-0000-{0:012d}'.format(i)
|
||||||
|
if i == 3 or i == 4:
|
||||||
volume['provider_location'] = None
|
volume['provider_location'] = None
|
||||||
else:
|
else:
|
||||||
volume['provider_location'] = '{0:d}'.format(i)
|
volume['provider_location'] = '{0:d}'.format(i)
|
||||||
volume['size'] = 128
|
volume['size'] = 128
|
||||||
if i == 2:
|
if i == 2:
|
||||||
volume['status'] = 'in-use'
|
volume['status'] = 'in-use'
|
||||||
|
elif i == 4:
|
||||||
|
volume['status'] = None
|
||||||
else:
|
else:
|
||||||
volume['status'] = 'available'
|
volume['status'] = 'available'
|
||||||
volume = fake_volume.fake_volume_obj(CTXT, **volume)
|
volume = fake_volume.fake_volume_obj(CTXT, **volume)
|
||||||
|
volume.volume_type = fake_volume.fake_volume_type_obj(CTXT)
|
||||||
TEST_VOLUME.append(volume)
|
TEST_VOLUME.append(volume)
|
||||||
|
|
||||||
|
|
||||||
@ -623,27 +627,39 @@ class VStorageRESTFCDriverTest(test.TestCase):
|
|||||||
self.driver.common.client.keep_session_loop.wait()
|
self.driver.common.client.keep_session_loop.wait()
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_create_volume(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_volume(
|
||||||
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
request.return_value = FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)
|
request.return_value = FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
self.driver.common._stats = {}
|
self.driver.common._stats = {}
|
||||||
self.driver.common._stats['pools'] = [
|
self.driver.common._stats['pools'] = [
|
||||||
{'location_info': {'pool_id': 30}}]
|
{'location_info': {'pool_id': 30}}]
|
||||||
ret = self.driver.create_volume(fake_volume.fake_volume_obj(self.ctxt))
|
ret = self.driver.create_volume(TEST_VOLUME[4])
|
||||||
self.assertEqual('1', ret['provider_location'])
|
self.assertEqual('1', ret['provider_location'])
|
||||||
self.assertEqual(2, request.call_count)
|
self.assertEqual(2, request.call_count)
|
||||||
|
|
||||||
@reduce_retrying_time
|
@reduce_retrying_time
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_create_volume_timeout(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_volume_timeout(
|
||||||
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
request.return_value = FakeResponse(
|
request.return_value = FakeResponse(
|
||||||
500, ERROR_RESULT,
|
500, ERROR_RESULT,
|
||||||
headers={'Content-Type': 'json'})
|
headers={'Content-Type': 'json'})
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
self.driver.common._stats = {}
|
self.driver.common._stats = {}
|
||||||
self.driver.common._stats['pools'] = [
|
self.driver.common._stats['pools'] = [
|
||||||
{'location_info': {'pool_id': 30}}]
|
{'location_info': {'pool_id': 30}}]
|
||||||
self.assertRaises(exception.VolumeDriverException,
|
self.assertRaises(exception.VolumeDriverException,
|
||||||
self.driver.create_volume,
|
self.driver.create_volume,
|
||||||
fake_volume.fake_volume_obj(self.ctxt))
|
TEST_VOLUME[4])
|
||||||
self.assertGreater(request.call_count, 1)
|
self.assertGreater(request.call_count, 1)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@ -706,12 +722,18 @@ class VStorageRESTFCDriverTest(test.TestCase):
|
|||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
||||||
def test_create_snapshot(self, volume_get, request):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_snapshot(
|
||||||
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
volume_get, request):
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
self.driver.common._stats = {}
|
self.driver.common._stats = {}
|
||||||
self.driver.common._stats['pools'] = [
|
self.driver.common._stats['pools'] = [
|
||||||
{'location_info': {'pool_id': 30}}]
|
{'location_info': {'pool_id': 30}}]
|
||||||
@ -745,12 +767,18 @@ class VStorageRESTFCDriverTest(test.TestCase):
|
|||||||
self.assertEqual(4, request.call_count)
|
self.assertEqual(4, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_create_cloned_volume(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_cloned_volume(
|
||||||
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
self.driver.common._stats = {}
|
self.driver.common._stats = {}
|
||||||
self.driver.common._stats['pools'] = [
|
self.driver.common._stats['pools'] = [
|
||||||
{'location_info': {'pool_id': 30}}]
|
{'location_info': {'pool_id': 30}}]
|
||||||
@ -759,12 +787,18 @@ class VStorageRESTFCDriverTest(test.TestCase):
|
|||||||
self.assertEqual(5, request.call_count)
|
self.assertEqual(5, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_create_volume_from_snapshot(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_volume_from_snapshot(
|
||||||
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
self.driver.common._stats = {}
|
self.driver.common._stats = {}
|
||||||
self.driver.common._stats['pools'] = [
|
self.driver.common._stats['pools'] = [
|
||||||
{'location_info': {'pool_id': 30}}]
|
{'location_info': {'pool_id': 30}}]
|
||||||
@ -775,9 +809,12 @@ class VStorageRESTFCDriverTest(test.TestCase):
|
|||||||
|
|
||||||
@mock.patch.object(fczm_utils, "add_fc_zone")
|
@mock.patch.object(fczm_utils, "add_fc_zone")
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_initialize_connection(self, request, add_fc_zone):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
def test_initialize_connection(
|
||||||
|
self, get_volume_type_extra_specs, request, add_fc_zone):
|
||||||
self.driver.common.conf.hitachi_zoning_request = True
|
self.driver.common.conf.hitachi_zoning_request = True
|
||||||
self.driver.common._lookup_service = FakeLookupService()
|
self.driver.common._lookup_service = FakeLookupService()
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
request.side_effect = [FakeResponse(200, GET_HOST_WWNS_RESULT),
|
request.side_effect = [FakeResponse(200, GET_HOST_WWNS_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
||||||
ret = self.driver.initialize_connection(
|
ret = self.driver.initialize_connection(
|
||||||
@ -790,10 +827,13 @@ class VStorageRESTFCDriverTest(test.TestCase):
|
|||||||
|
|
||||||
@mock.patch.object(fczm_utils, "add_fc_zone")
|
@mock.patch.object(fczm_utils, "add_fc_zone")
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_initialize_connection_already_mapped(self, request, add_fc_zone):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
def test_initialize_connection_already_mapped(
|
||||||
|
self, get_volume_type_extra_specs, request, add_fc_zone):
|
||||||
"""Normal case: ldev have already mapped."""
|
"""Normal case: ldev have already mapped."""
|
||||||
self.driver.common.conf.hitachi_zoning_request = True
|
self.driver.common.conf.hitachi_zoning_request = True
|
||||||
self.driver.common._lookup_service = FakeLookupService()
|
self.driver.common._lookup_service = FakeLookupService()
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
request.side_effect = [
|
request.side_effect = [
|
||||||
FakeResponse(200, GET_HOST_WWNS_RESULT),
|
FakeResponse(200, GET_HOST_WWNS_RESULT),
|
||||||
FakeResponse(202, COMPLETED_FAILED_RESULT_LU_DEFINED),
|
FakeResponse(202, COMPLETED_FAILED_RESULT_LU_DEFINED),
|
||||||
@ -809,10 +849,13 @@ class VStorageRESTFCDriverTest(test.TestCase):
|
|||||||
|
|
||||||
@mock.patch.object(fczm_utils, "add_fc_zone")
|
@mock.patch.object(fczm_utils, "add_fc_zone")
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_initialize_connection_shared_target(self, request, add_fc_zone):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
def test_initialize_connection_shared_target(
|
||||||
|
self, get_volume_type_extra_specs, request, add_fc_zone):
|
||||||
"""Normal case: A target shared with other systems."""
|
"""Normal case: A target shared with other systems."""
|
||||||
self.driver.common.conf.hitachi_zoning_request = True
|
self.driver.common.conf.hitachi_zoning_request = True
|
||||||
self.driver.common._lookup_service = FakeLookupService()
|
self.driver.common._lookup_service = FakeLookupService()
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
request.side_effect = [FakeResponse(200, NOTFOUND_RESULT),
|
request.side_effect = [FakeResponse(200, NOTFOUND_RESULT),
|
||||||
FakeResponse(200, NOTFOUND_RESULT),
|
FakeResponse(200, NOTFOUND_RESULT),
|
||||||
FakeResponse(200, GET_HOST_GROUPS_RESULT),
|
FakeResponse(200, GET_HOST_GROUPS_RESULT),
|
||||||
@ -901,27 +944,36 @@ class VStorageRESTFCDriverTest(test.TestCase):
|
|||||||
self.assertEqual(1, remove_fc_zone.call_count)
|
self.assertEqual(1, remove_fc_zone.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_manage_existing(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_manage_existing(self, get_volume_type_qos_specs, request):
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
|
FakeResponse(200, GET_LDEVS_RESULT)]
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
ret = self.driver.manage_existing(
|
ret = self.driver.manage_existing(
|
||||||
TEST_VOLUME[0], self.test_existing_ref)
|
TEST_VOLUME[0], self.test_existing_ref)
|
||||||
self.assertEqual('1', ret['provider_location'])
|
self.assertEqual('1', ret['provider_location'])
|
||||||
self.assertEqual(2, request.call_count)
|
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
|
||||||
def test_manage_existing_name(self, request):
|
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEVS_RESULT),
|
|
||||||
FakeResponse(200, GET_LDEV_RESULT),
|
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
|
||||||
ret = self.driver.manage_existing(
|
|
||||||
TEST_VOLUME[0], self.test_existing_ref_name)
|
|
||||||
self.assertEqual('1', ret['provider_location'])
|
|
||||||
self.assertEqual(3, request.call_count)
|
self.assertEqual(3, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_manage_existing_get_size(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_manage_existing_name(self, get_volume_type_qos_specs, request):
|
||||||
|
request.side_effect = [FakeResponse(200, GET_LDEVS_RESULT),
|
||||||
|
FakeResponse(200, GET_LDEV_RESULT),
|
||||||
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
|
FakeResponse(200, GET_LDEVS_RESULT)]
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
|
ret = self.driver.manage_existing(
|
||||||
|
TEST_VOLUME[0], self.test_existing_ref_name)
|
||||||
|
self.assertEqual('1', ret['provider_location'])
|
||||||
|
self.assertEqual(4, request.call_count)
|
||||||
|
|
||||||
|
@mock.patch.object(requests.Session, "request")
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_manage_existing_get_size(
|
||||||
|
self, get_volume_type_qos_specs, request):
|
||||||
request.return_value = FakeResponse(200, GET_LDEV_RESULT)
|
request.return_value = FakeResponse(200, GET_LDEV_RESULT)
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
self.driver.manage_existing_get_size(
|
self.driver.manage_existing_get_size(
|
||||||
TEST_VOLUME[0], self.test_existing_ref)
|
TEST_VOLUME[0], self.test_existing_ref)
|
||||||
self.assertEqual(1, request.call_count)
|
self.assertEqual(1, request.call_count)
|
||||||
@ -1031,7 +1083,13 @@ class VStorageRESTFCDriverTest(test.TestCase):
|
|||||||
self.assertTupleEqual(actual, ret)
|
self.assertTupleEqual(actual, ret)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_create_group_from_src_volume(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_group_from_src_volume(
|
||||||
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
@ -1050,12 +1108,18 @@ class VStorageRESTFCDriverTest(test.TestCase):
|
|||||||
self.assertTupleEqual(actual, ret)
|
self.assertTupleEqual(actual, ret)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_create_group_from_src_snapshot(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_group_from_src_snapshot(
|
||||||
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
self.driver.common._stats = {}
|
self.driver.common._stats = {}
|
||||||
self.driver.common._stats['pools'] = [
|
self.driver.common._stats['pools'] = [
|
||||||
{'location_info': {'pool_id': 30}}]
|
{'location_info': {'pool_id': 30}}]
|
||||||
@ -1068,7 +1132,10 @@ class VStorageRESTFCDriverTest(test.TestCase):
|
|||||||
None, [{'id': TEST_VOLUME[0]['id'], 'provider_location': '1'}])
|
None, [{'id': TEST_VOLUME[0]['id'], 'provider_location': '1'}])
|
||||||
self.assertTupleEqual(actual, ret)
|
self.assertTupleEqual(actual, ret)
|
||||||
|
|
||||||
def test_create_group_from_src_volume_error(self):
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_group_from_src_volume_error(
|
||||||
|
self, get_volume_type_qos_specs):
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exception.VolumeDriverException, self.driver.create_group_from_src,
|
exception.VolumeDriverException, self.driver.create_group_from_src,
|
||||||
self.ctxt, TEST_GROUP[1], [TEST_VOLUME[1]],
|
self.ctxt, TEST_GROUP[1], [TEST_VOLUME[1]],
|
||||||
@ -1094,9 +1161,14 @@ class VStorageRESTFCDriverTest(test.TestCase):
|
|||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
||||||
@mock.patch.object(volume_utils, 'is_group_a_cg_snapshot_type')
|
@mock.patch.object(volume_utils, 'is_group_a_cg_snapshot_type')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
def test_create_group_snapshot_non_cg(
|
def test_create_group_snapshot_non_cg(
|
||||||
self, is_group_a_cg_snapshot_type, volume_get, request):
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
is_group_a_cg_snapshot_type, volume_get, request):
|
||||||
is_group_a_cg_snapshot_type.return_value = False
|
is_group_a_cg_snapshot_type.return_value = False
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
@ -1120,9 +1192,14 @@ class VStorageRESTFCDriverTest(test.TestCase):
|
|||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
||||||
@mock.patch.object(volume_utils, 'is_group_a_cg_snapshot_type')
|
@mock.patch.object(volume_utils, 'is_group_a_cg_snapshot_type')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
def test_create_group_snapshot_cg(
|
def test_create_group_snapshot_cg(
|
||||||
self, is_group_a_cg_snapshot_type, volume_get, request):
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
is_group_a_cg_snapshot_type, volume_get, request):
|
||||||
is_group_a_cg_snapshot_type.return_value = True
|
is_group_a_cg_snapshot_type.return_value = True
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
request.side_effect = [FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
request.side_effect = [FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
|
@ -70,20 +70,24 @@ DEFAULT_CONNECTOR = {
|
|||||||
CTXT = cinder_context.get_admin_context()
|
CTXT = cinder_context.get_admin_context()
|
||||||
|
|
||||||
TEST_VOLUME = []
|
TEST_VOLUME = []
|
||||||
for i in range(4):
|
for i in range(5):
|
||||||
volume = {}
|
volume = {}
|
||||||
volume['id'] = '00000000-0000-0000-0000-{0:012d}'.format(i)
|
volume['id'] = '00000000-0000-0000-0000-{0:012d}'.format(i)
|
||||||
volume['name'] = 'test-volume{0:d}'.format(i)
|
volume['name'] = 'test-volume{0:d}'.format(i)
|
||||||
if i == 3:
|
volume['volume_type_id'] = '00000000-0000-0000-0000-{0:012d}'.format(i)
|
||||||
|
if i == 3 or i == 4:
|
||||||
volume['provider_location'] = None
|
volume['provider_location'] = None
|
||||||
else:
|
else:
|
||||||
volume['provider_location'] = '{0:d}'.format(i)
|
volume['provider_location'] = '{0:d}'.format(i)
|
||||||
volume['size'] = 128
|
volume['size'] = 128
|
||||||
if i == 2:
|
if i == 2:
|
||||||
volume['status'] = 'in-use'
|
volume['status'] = 'in-use'
|
||||||
|
elif i == 4:
|
||||||
|
volume['status'] = None
|
||||||
else:
|
else:
|
||||||
volume['status'] = 'available'
|
volume['status'] = 'available'
|
||||||
volume = fake_volume.fake_volume_obj(CTXT, **volume)
|
volume = fake_volume.fake_volume_obj(CTXT, **volume)
|
||||||
|
volume.volume_type = fake_volume.fake_volume_type_obj(CTXT)
|
||||||
TEST_VOLUME.append(volume)
|
TEST_VOLUME.append(volume)
|
||||||
|
|
||||||
|
|
||||||
@ -579,12 +583,18 @@ class VStorageRESTISCSIDriverTest(test.TestCase):
|
|||||||
self.assertEqual(1, get_goodness_function.call_count)
|
self.assertEqual(1, get_goodness_function.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_create_volume(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_volume(
|
||||||
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
request.return_value = FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)
|
request.return_value = FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
self.driver.common._stats = {}
|
self.driver.common._stats = {}
|
||||||
self.driver.common._stats['pools'] = [
|
self.driver.common._stats['pools'] = [
|
||||||
{'location_info': {'pool_id': 30}}]
|
{'location_info': {'pool_id': 30}}]
|
||||||
ret = self.driver.create_volume(fake_volume.fake_volume_obj(self.ctxt))
|
ret = self.driver.create_volume(TEST_VOLUME[4])
|
||||||
self.assertEqual('1', ret['provider_location'])
|
self.assertEqual('1', ret['provider_location'])
|
||||||
self.assertEqual(2, request.call_count)
|
self.assertEqual(2, request.call_count)
|
||||||
|
|
||||||
@ -599,12 +609,18 @@ class VStorageRESTISCSIDriverTest(test.TestCase):
|
|||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
||||||
def test_create_snapshot(self, volume_get, request):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_snapshot(
|
||||||
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
volume_get, request):
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
self.driver.common._stats = {}
|
self.driver.common._stats = {}
|
||||||
self.driver.common._stats['pools'] = [
|
self.driver.common._stats['pools'] = [
|
||||||
{'location_info': {'pool_id': 30}}]
|
{'location_info': {'pool_id': 30}}]
|
||||||
@ -622,12 +638,18 @@ class VStorageRESTISCSIDriverTest(test.TestCase):
|
|||||||
self.assertEqual(4, request.call_count)
|
self.assertEqual(4, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_create_cloned_volume(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_cloned_volume(
|
||||||
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
self.driver.common._stats = {}
|
self.driver.common._stats = {}
|
||||||
self.driver.common._stats['pools'] = [
|
self.driver.common._stats['pools'] = [
|
||||||
{'location_info': {'pool_id': 30}}]
|
{'location_info': {'pool_id': 30}}]
|
||||||
@ -636,12 +658,18 @@ class VStorageRESTISCSIDriverTest(test.TestCase):
|
|||||||
self.assertEqual(5, request.call_count)
|
self.assertEqual(5, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_create_volume_from_snapshot(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_volume_from_snapshot(
|
||||||
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
self.driver.common._stats = {}
|
self.driver.common._stats = {}
|
||||||
self.driver.common._stats['pools'] = [
|
self.driver.common._stats['pools'] = [
|
||||||
{'location_info': {'pool_id': 30}}]
|
{'location_info': {'pool_id': 30}}]
|
||||||
@ -651,10 +679,13 @@ class VStorageRESTISCSIDriverTest(test.TestCase):
|
|||||||
self.assertEqual(5, request.call_count)
|
self.assertEqual(5, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_initialize_connection(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
def test_initialize_connection(
|
||||||
|
self, get_volume_type_extra_specs, request):
|
||||||
request.side_effect = [FakeResponse(200, GET_HOST_ISCSIS_RESULT),
|
request.side_effect = [FakeResponse(200, GET_HOST_ISCSIS_RESULT),
|
||||||
FakeResponse(200, GET_HOST_GROUP_RESULT),
|
FakeResponse(200, GET_HOST_GROUP_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
ret = self.driver.initialize_connection(
|
ret = self.driver.initialize_connection(
|
||||||
TEST_VOLUME[0], DEFAULT_CONNECTOR)
|
TEST_VOLUME[0], DEFAULT_CONNECTOR)
|
||||||
self.assertEqual('iscsi', ret['driver_volume_type'])
|
self.assertEqual('iscsi', ret['driver_volume_type'])
|
||||||
@ -674,12 +705,15 @@ class VStorageRESTISCSIDriverTest(test.TestCase):
|
|||||||
self.assertEqual(3, request.call_count)
|
self.assertEqual(3, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_initialize_connection_shared_target(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
def test_initialize_connection_shared_target(
|
||||||
|
self, get_volume_type_extra_specs, request):
|
||||||
"""Normal case: A target shared with other systems."""
|
"""Normal case: A target shared with other systems."""
|
||||||
request.side_effect = [FakeResponse(200, NOTFOUND_RESULT),
|
request.side_effect = [FakeResponse(200, NOTFOUND_RESULT),
|
||||||
FakeResponse(200, GET_HOST_GROUPS_RESULT),
|
FakeResponse(200, GET_HOST_GROUPS_RESULT),
|
||||||
FakeResponse(200, GET_HOST_ISCSIS_RESULT),
|
FakeResponse(200, GET_HOST_ISCSIS_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
ret = self.driver.initialize_connection(
|
ret = self.driver.initialize_connection(
|
||||||
TEST_VOLUME[0], DEFAULT_CONNECTOR)
|
TEST_VOLUME[0], DEFAULT_CONNECTOR)
|
||||||
self.assertEqual('iscsi', ret['driver_volume_type'])
|
self.assertEqual('iscsi', ret['driver_volume_type'])
|
||||||
@ -760,23 +794,29 @@ class VStorageRESTISCSIDriverTest(test.TestCase):
|
|||||||
self.assertEqual(6, request.call_count)
|
self.assertEqual(6, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_manage_existing(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_manage_existing(self, get_volume_type_qos_specs, request):
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
|
FakeResponse(200, GET_LDEVS_RESULT)]
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
ret = self.driver.manage_existing(
|
ret = self.driver.manage_existing(
|
||||||
TEST_VOLUME[0], self.test_existing_ref)
|
TEST_VOLUME[0], self.test_existing_ref)
|
||||||
self.assertEqual('1', ret['provider_location'])
|
self.assertEqual('1', ret['provider_location'])
|
||||||
self.assertEqual(2, request.call_count)
|
self.assertEqual(3, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_manage_existing_name(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_manage_existing_name(self, get_volume_type_qos_specs, request):
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEVS_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEVS_RESULT),
|
||||||
FakeResponse(200, GET_LDEV_RESULT),
|
FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
|
FakeResponse(200, GET_LDEVS_RESULT)]
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
ret = self.driver.manage_existing(
|
ret = self.driver.manage_existing(
|
||||||
TEST_VOLUME[0], self.test_existing_ref_name)
|
TEST_VOLUME[0], self.test_existing_ref_name)
|
||||||
self.assertEqual('1', ret['provider_location'])
|
self.assertEqual('1', ret['provider_location'])
|
||||||
self.assertEqual(3, request.call_count)
|
self.assertEqual(4, request.call_count)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_manage_existing_get_size(self, request):
|
def test_manage_existing_get_size(self, request):
|
||||||
@ -884,12 +924,18 @@ class VStorageRESTISCSIDriverTest(test.TestCase):
|
|||||||
self.assertTupleEqual(actual, ret)
|
self.assertTupleEqual(actual, ret)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_create_group_from_src_volume(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_group_from_src_volume(
|
||||||
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
self.driver.common._stats = {}
|
self.driver.common._stats = {}
|
||||||
self.driver.common._stats['pools'] = [
|
self.driver.common._stats['pools'] = [
|
||||||
{'location_info': {'pool_id': 30}}]
|
{'location_info': {'pool_id': 30}}]
|
||||||
@ -903,12 +949,18 @@ class VStorageRESTISCSIDriverTest(test.TestCase):
|
|||||||
self.assertTupleEqual(actual, ret)
|
self.assertTupleEqual(actual, ret)
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_create_group_from_src_snapshot(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_group_from_src_snapshot(
|
||||||
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
FakeResponse(200, GET_SNAPSHOTS_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
self.driver.common._stats = {}
|
self.driver.common._stats = {}
|
||||||
self.driver.common._stats['pools'] = [
|
self.driver.common._stats['pools'] = [
|
||||||
{'location_info': {'pool_id': 30}}]
|
{'location_info': {'pool_id': 30}}]
|
||||||
@ -921,7 +973,10 @@ class VStorageRESTISCSIDriverTest(test.TestCase):
|
|||||||
None, [{'id': TEST_VOLUME[0]['id'], 'provider_location': '1'}])
|
None, [{'id': TEST_VOLUME[0]['id'], 'provider_location': '1'}])
|
||||||
self.assertTupleEqual(actual, ret)
|
self.assertTupleEqual(actual, ret)
|
||||||
|
|
||||||
def test_create_group_from_src_volume_error(self):
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_group_from_src_volume_error(
|
||||||
|
self, get_volume_type_qos_specs):
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exception.VolumeDriverException, self.driver.create_group_from_src,
|
exception.VolumeDriverException, self.driver.create_group_from_src,
|
||||||
self.ctxt, TEST_GROUP[1], [TEST_VOLUME[1]],
|
self.ctxt, TEST_GROUP[1], [TEST_VOLUME[1]],
|
||||||
@ -947,9 +1002,14 @@ class VStorageRESTISCSIDriverTest(test.TestCase):
|
|||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
||||||
@mock.patch.object(volume_utils, 'is_group_a_cg_snapshot_type')
|
@mock.patch.object(volume_utils, 'is_group_a_cg_snapshot_type')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
def test_create_group_snapshot_non_cg(
|
def test_create_group_snapshot_non_cg(
|
||||||
self, is_group_a_cg_snapshot_type, volume_get, request):
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
is_group_a_cg_snapshot_type, volume_get, request):
|
||||||
is_group_a_cg_snapshot_type.return_value = False
|
is_group_a_cg_snapshot_type.return_value = False
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
@ -973,9 +1033,14 @@ class VStorageRESTISCSIDriverTest(test.TestCase):
|
|||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
@mock.patch.object(sqlalchemy_api, 'volume_get', side_effect=_volume_get)
|
||||||
@mock.patch.object(volume_utils, 'is_group_a_cg_snapshot_type')
|
@mock.patch.object(volume_utils, 'is_group_a_cg_snapshot_type')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
def test_create_group_snapshot_cg(
|
def test_create_group_snapshot_cg(
|
||||||
self, is_group_a_cg_snapshot_type, volume_get, request):
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
is_group_a_cg_snapshot_type, volume_get, request):
|
||||||
is_group_a_cg_snapshot_type.return_value = True
|
is_group_a_cg_snapshot_type.return_value = True
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
request.side_effect = [FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
request.side_effect = [FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT),
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Copyright (C) 2021, 2023, NEC corporation
|
# Copyright (C) 2021, 2024, NEC corporation
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
# not use this file except in compliance with the License. You may obtain
|
# not use this file except in compliance with the License. You may obtain
|
||||||
@ -28,6 +28,7 @@ from cinder.volume.drivers.hitachi import hbsd_rest
|
|||||||
from cinder.volume.drivers.hitachi import hbsd_rest_api
|
from cinder.volume.drivers.hitachi import hbsd_rest_api
|
||||||
from cinder.volume.drivers.nec.v import nec_v_fc
|
from cinder.volume.drivers.nec.v import nec_v_fc
|
||||||
from cinder.volume.drivers.nec.v import nec_v_rest
|
from cinder.volume.drivers.nec.v import nec_v_rest
|
||||||
|
from cinder.volume import volume_types
|
||||||
from cinder.volume import volume_utils
|
from cinder.volume import volume_utils
|
||||||
|
|
||||||
# Configuration parameter values
|
# Configuration parameter values
|
||||||
@ -56,6 +57,17 @@ DEFAULT_CONNECTOR = {
|
|||||||
'multipath': False,
|
'multipath': False,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CTXT = cinder_context.get_admin_context()
|
||||||
|
|
||||||
|
TEST_VOLUME = []
|
||||||
|
volume = {}
|
||||||
|
volume['id'] = '00000000-0000-0000-0000-{0:012d}'.format(0)
|
||||||
|
volume['name'] = 'test-volume{0:d}'.format(0)
|
||||||
|
volume['volume_type_id'] = '00000000-0000-0000-0000-{0:012d}'.format(0)
|
||||||
|
volume = fake_volume.fake_volume_obj(CTXT, **volume)
|
||||||
|
volume.volume_type = fake_volume.fake_volume_type_obj(CTXT)
|
||||||
|
TEST_VOLUME.append(volume)
|
||||||
|
|
||||||
# Dummy response for REST API
|
# Dummy response for REST API
|
||||||
POST_SESSIONS_RESULT = {
|
POST_SESSIONS_RESULT = {
|
||||||
"token": "b74777a3-f9f0-4ea8-bd8f-09847fac48d3",
|
"token": "b74777a3-f9f0-4ea8-bd8f-09847fac48d3",
|
||||||
@ -376,11 +388,17 @@ class VStorageRESTFCDriverTest(test.TestCase):
|
|||||||
"SS")
|
"SS")
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_create_volume(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_volume(
|
||||||
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
request.return_value = FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)
|
request.return_value = FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
self.driver.common._stats = {}
|
self.driver.common._stats = {}
|
||||||
self.driver.common._stats['pools'] = [
|
self.driver.common._stats['pools'] = [
|
||||||
{'location_info': {'pool_id': 30}}]
|
{'location_info': {'pool_id': 30}}]
|
||||||
ret = self.driver.create_volume(fake_volume.fake_volume_obj(self.ctxt))
|
ret = self.driver.create_volume(TEST_VOLUME[0])
|
||||||
self.assertEqual('1', ret['provider_location'])
|
self.assertEqual('1', ret['provider_location'])
|
||||||
self.assertEqual(2, request.call_count)
|
self.assertEqual(2, request.call_count)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Copyright (C) 2021, 2023, NEC corporation
|
# Copyright (C) 2021, 2024, NEC corporation
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
@ -29,6 +29,7 @@ from cinder.volume.drivers.hitachi import hbsd_rest
|
|||||||
from cinder.volume.drivers.hitachi import hbsd_rest_api
|
from cinder.volume.drivers.hitachi import hbsd_rest_api
|
||||||
from cinder.volume.drivers.nec.v import nec_v_iscsi
|
from cinder.volume.drivers.nec.v import nec_v_iscsi
|
||||||
from cinder.volume.drivers.nec.v import nec_v_rest
|
from cinder.volume.drivers.nec.v import nec_v_rest
|
||||||
|
from cinder.volume import volume_types
|
||||||
from cinder.volume import volume_utils
|
from cinder.volume import volume_utils
|
||||||
|
|
||||||
# Configuration parameter values
|
# Configuration parameter values
|
||||||
@ -57,6 +58,17 @@ DEFAULT_CONNECTOR = {
|
|||||||
'multipath': False,
|
'multipath': False,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CTXT = cinder_context.get_admin_context()
|
||||||
|
|
||||||
|
TEST_VOLUME = []
|
||||||
|
volume = {}
|
||||||
|
volume['id'] = '00000000-0000-0000-0000-{0:012d}'.format(0)
|
||||||
|
volume['name'] = 'test-volume{0:d}'.format(0)
|
||||||
|
volume['volume_type_id'] = '00000000-0000-0000-0000-{0:012d}'.format(0)
|
||||||
|
volume = fake_volume.fake_volume_obj(CTXT, **volume)
|
||||||
|
volume.volume_type = fake_volume.fake_volume_type_obj(CTXT)
|
||||||
|
TEST_VOLUME.append(volume)
|
||||||
|
|
||||||
# Dummy response for REST API
|
# Dummy response for REST API
|
||||||
POST_SESSIONS_RESULT = {
|
POST_SESSIONS_RESULT = {
|
||||||
"token": "b74777a3-f9f0-4ea8-bd8f-09847fac48d3",
|
"token": "b74777a3-f9f0-4ea8-bd8f-09847fac48d3",
|
||||||
@ -396,11 +408,17 @@ class VStorageRESTISCSIDriverTest(test.TestCase):
|
|||||||
"SS")
|
"SS")
|
||||||
|
|
||||||
@mock.patch.object(requests.Session, "request")
|
@mock.patch.object(requests.Session, "request")
|
||||||
def test_create_volume(self, request):
|
@mock.patch.object(volume_types, 'get_volume_type_extra_specs')
|
||||||
|
@mock.patch.object(volume_types, 'get_volume_type_qos_specs')
|
||||||
|
def test_create_volume(
|
||||||
|
self, get_volume_type_qos_specs, get_volume_type_extra_specs,
|
||||||
|
request):
|
||||||
request.return_value = FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)
|
request.return_value = FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)
|
||||||
|
get_volume_type_extra_specs.return_value = {}
|
||||||
|
get_volume_type_qos_specs.return_value = {'qos_specs': None}
|
||||||
self.driver.common._stats = {}
|
self.driver.common._stats = {}
|
||||||
self.driver.common._stats['pools'] = [
|
self.driver.common._stats['pools'] = [
|
||||||
{'location_info': {'pool_id': 30}}]
|
{'location_info': {'pool_id': 30}}]
|
||||||
ret = self.driver.create_volume(fake_volume.fake_volume_obj(self.ctxt))
|
ret = self.driver.create_volume(TEST_VOLUME[0])
|
||||||
self.assertEqual('1', ret['provider_location'])
|
self.assertEqual('1', ret['provider_location'])
|
||||||
self.assertEqual(2, request.call_count)
|
self.assertEqual(2, request.call_count)
|
||||||
|
@ -252,7 +252,8 @@ class HBSDCommon():
|
|||||||
return pool['location_info']['pool_id']
|
return pool['location_info']['pool_id']
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def create_ldev(self, size, extra_specs, pool_id, ldev_range):
|
def create_ldev(
|
||||||
|
self, size, extra_specs, pool_id, ldev_range, qos_specs=None):
|
||||||
"""Create an LDEV and return its LDEV number."""
|
"""Create an LDEV and return its LDEV number."""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
@ -265,9 +266,10 @@ class HBSDCommon():
|
|||||||
extra_specs = self.get_volume_extra_specs(volume)
|
extra_specs = self.get_volume_extra_specs(volume)
|
||||||
pool_id = self.get_pool_id_of_volume(volume)
|
pool_id = self.get_pool_id_of_volume(volume)
|
||||||
ldev_range = self.storage_info['ldev_range']
|
ldev_range = self.storage_info['ldev_range']
|
||||||
|
qos_specs = utils.get_qos_specs_from_volume(volume)
|
||||||
try:
|
try:
|
||||||
ldev = self.create_ldev(
|
ldev = self.create_ldev(volume['size'], extra_specs, pool_id,
|
||||||
volume['size'], extra_specs, pool_id, ldev_range)
|
ldev_range, qos_specs=qos_specs)
|
||||||
except Exception:
|
except Exception:
|
||||||
with excutils.save_and_reraise_exception():
|
with excutils.save_and_reraise_exception():
|
||||||
self.output_log(MSG.CREATE_LDEV_FAILED)
|
self.output_log(MSG.CREATE_LDEV_FAILED)
|
||||||
@ -291,13 +293,14 @@ class HBSDCommon():
|
|||||||
|
|
||||||
def copy_on_storage(
|
def copy_on_storage(
|
||||||
self, pvol, size, extra_specs, pool_id, snap_pool_id, ldev_range,
|
self, pvol, size, extra_specs, pool_id, snap_pool_id, ldev_range,
|
||||||
is_snapshot=False, sync=False, is_rep=False):
|
is_snapshot=False, sync=False, is_rep=False, qos_specs=None):
|
||||||
"""Create a copy of the specified LDEV on the storage."""
|
"""Create a copy of the specified LDEV on the storage."""
|
||||||
ldev_info = self.get_ldev_info(['status', 'attributes'], pvol)
|
ldev_info = self.get_ldev_info(['status', 'attributes'], pvol)
|
||||||
if ldev_info['status'] != 'NML':
|
if ldev_info['status'] != 'NML':
|
||||||
msg = self.output_log(MSG.INVALID_LDEV_STATUS_FOR_COPY, ldev=pvol)
|
msg = self.output_log(MSG.INVALID_LDEV_STATUS_FOR_COPY, ldev=pvol)
|
||||||
self.raise_error(msg)
|
self.raise_error(msg)
|
||||||
svol = self.create_ldev(size, extra_specs, pool_id, ldev_range)
|
svol = self.create_ldev(
|
||||||
|
size, extra_specs, pool_id, ldev_range, qos_specs=qos_specs)
|
||||||
try:
|
try:
|
||||||
self.create_pair_on_storage(
|
self.create_pair_on_storage(
|
||||||
pvol, svol, snap_pool_id, is_snapshot=is_snapshot)
|
pvol, svol, snap_pool_id, is_snapshot=is_snapshot)
|
||||||
@ -326,9 +329,10 @@ class HBSDCommon():
|
|||||||
pool_id = self.get_pool_id_of_volume(volume)
|
pool_id = self.get_pool_id_of_volume(volume)
|
||||||
snap_pool_id = self.storage_info['snap_pool_id']
|
snap_pool_id = self.storage_info['snap_pool_id']
|
||||||
ldev_range = self.storage_info['ldev_range']
|
ldev_range = self.storage_info['ldev_range']
|
||||||
|
qos_specs = utils.get_qos_specs_from_volume(volume)
|
||||||
new_ldev = self.copy_on_storage(ldev, size, extra_specs, pool_id,
|
new_ldev = self.copy_on_storage(ldev, size, extra_specs, pool_id,
|
||||||
snap_pool_id, ldev_range,
|
snap_pool_id, ldev_range,
|
||||||
is_rep=is_rep)
|
is_rep=is_rep, qos_specs=qos_specs)
|
||||||
self.modify_ldev_name(new_ldev, volume['id'].replace("-", ""))
|
self.modify_ldev_name(new_ldev, volume['id'].replace("-", ""))
|
||||||
if is_rep:
|
if is_rep:
|
||||||
self.delete_pair(new_ldev)
|
self.delete_pair(new_ldev)
|
||||||
@ -483,9 +487,10 @@ class HBSDCommon():
|
|||||||
pool_id = self.get_pool_id_of_volume(snapshot['volume'])
|
pool_id = self.get_pool_id_of_volume(snapshot['volume'])
|
||||||
snap_pool_id = self.storage_info['snap_pool_id']
|
snap_pool_id = self.storage_info['snap_pool_id']
|
||||||
ldev_range = self.storage_info['ldev_range']
|
ldev_range = self.storage_info['ldev_range']
|
||||||
|
qos_specs = utils.get_qos_specs_from_volume(snapshot)
|
||||||
new_ldev = self.copy_on_storage(
|
new_ldev = self.copy_on_storage(
|
||||||
ldev, size, extra_specs, pool_id, snap_pool_id, ldev_range,
|
ldev, size, extra_specs, pool_id, snap_pool_id, ldev_range,
|
||||||
is_snapshot=True)
|
is_snapshot=True, qos_specs=qos_specs)
|
||||||
self.modify_ldev_name(new_ldev, snapshot.id.replace("-", ""))
|
self.modify_ldev_name(new_ldev, snapshot.id.replace("-", ""))
|
||||||
return {
|
return {
|
||||||
'provider_location': str(new_ldev),
|
'provider_location': str(new_ldev),
|
||||||
@ -535,7 +540,7 @@ class HBSDCommon():
|
|||||||
single_pool.update(dict(
|
single_pool.update(dict(
|
||||||
pool_name=pool_name,
|
pool_name=pool_name,
|
||||||
reserved_percentage=self.conf.safe_get('reserved_percentage'),
|
reserved_percentage=self.conf.safe_get('reserved_percentage'),
|
||||||
QoS_support=False,
|
QoS_support=True,
|
||||||
thin_provisioning_support=True,
|
thin_provisioning_support=True,
|
||||||
thick_provisioning_support=False,
|
thick_provisioning_support=False,
|
||||||
multiattach=True,
|
multiattach=True,
|
||||||
@ -621,6 +626,12 @@ class HBSDCommon():
|
|||||||
"""Check if the LDEV meets the criteria for being managed."""
|
"""Check if the LDEV meets the criteria for being managed."""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def get_qos_specs_from_ldev(self, ldev):
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def change_qos_specs(self, ldev, old_qos_specs, new_qos_specs):
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
def manage_existing(self, volume, existing_ref):
|
def manage_existing(self, volume, existing_ref):
|
||||||
"""Return volume properties which Cinder needs to manage the volume."""
|
"""Return volume properties which Cinder needs to manage the volume."""
|
||||||
if 'source-name' in existing_ref:
|
if 'source-name' in existing_ref:
|
||||||
@ -630,6 +641,10 @@ class HBSDCommon():
|
|||||||
ldev = str2int(existing_ref.get('source-id'))
|
ldev = str2int(existing_ref.get('source-id'))
|
||||||
self.check_ldev_manageability(ldev, existing_ref)
|
self.check_ldev_manageability(ldev, existing_ref)
|
||||||
self.modify_ldev_name(ldev, volume['id'].replace("-", ""))
|
self.modify_ldev_name(ldev, volume['id'].replace("-", ""))
|
||||||
|
new_qos_specs = utils.get_qos_specs_from_volume(volume)
|
||||||
|
old_qos_specs = self.get_qos_specs_from_ldev(ldev)
|
||||||
|
if old_qos_specs != new_qos_specs:
|
||||||
|
self.change_qos_specs(ldev, old_qos_specs, new_qos_specs)
|
||||||
return {
|
return {
|
||||||
'provider_location': str(ldev),
|
'provider_location': str(ldev),
|
||||||
}
|
}
|
||||||
|
@ -80,6 +80,7 @@ class HBSDFCDriver(driver.FibreChannelDriver):
|
|||||||
2.3.3 - Add GAD volume support.
|
2.3.3 - Add GAD volume support.
|
||||||
2.3.4 - Support data deduplication and compression.
|
2.3.4 - Support data deduplication and compression.
|
||||||
2.3.5 - Fix key error when backend is down.
|
2.3.5 - Fix key error when backend is down.
|
||||||
|
2.4.0 - Add QoS support.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -80,6 +80,7 @@ class HBSDISCSIDriver(driver.ISCSIDriver):
|
|||||||
2.3.3 - Add GAD volume support.
|
2.3.3 - Add GAD volume support.
|
||||||
2.3.4 - Support data deduplication and compression.
|
2.3.4 - Support data deduplication and compression.
|
||||||
2.3.5 - Fix key error when backend is down.
|
2.3.5 - Fix key error when backend is down.
|
||||||
|
2.4.0 - Add QoS support.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -345,16 +345,18 @@ class HBSDREPLICATION(rest.HBSDREST):
|
|||||||
"""Create a primary volume and a secondary volume."""
|
"""Create a primary volume and a secondary volume."""
|
||||||
pool_id = self.rep_secondary.storage_info['pool_id'][0]
|
pool_id = self.rep_secondary.storage_info['pool_id'][0]
|
||||||
ldev_range = self.rep_secondary.storage_info['ldev_range']
|
ldev_range = self.rep_secondary.storage_info['ldev_range']
|
||||||
|
qos_specs = utils.get_qos_specs_from_volume(volume)
|
||||||
thread = greenthread.spawn(
|
thread = greenthread.spawn(
|
||||||
self.rep_secondary.create_ldev, volume.size, extra_specs,
|
self.rep_secondary.create_ldev, volume.size, extra_specs,
|
||||||
pool_id, ldev_range)
|
pool_id, ldev_range, qos_specs=qos_specs)
|
||||||
if pvol is None:
|
if pvol is None:
|
||||||
try:
|
try:
|
||||||
pool_id = self.rep_primary.get_pool_id_of_volume(volume)
|
pool_id = self.rep_primary.get_pool_id_of_volume(volume)
|
||||||
ldev_range = self.rep_primary.storage_info['ldev_range']
|
ldev_range = self.rep_primary.storage_info['ldev_range']
|
||||||
pvol = self.rep_primary.create_ldev(volume.size,
|
pvol = self.rep_primary.create_ldev(volume.size,
|
||||||
extra_specs,
|
extra_specs,
|
||||||
pool_id, ldev_range)
|
pool_id, ldev_range,
|
||||||
|
qos_specs=qos_specs)
|
||||||
except exception.VolumeDriverException:
|
except exception.VolumeDriverException:
|
||||||
self.rep_primary.output_log(MSG.CREATE_LDEV_FAILED)
|
self.rep_primary.output_log(MSG.CREATE_LDEV_FAILED)
|
||||||
try:
|
try:
|
||||||
|
@ -360,11 +360,24 @@ class HBSDREST(common.HBSDCommon):
|
|||||||
body['endLdevId'] = max_ldev
|
body['endLdevId'] = max_ldev
|
||||||
return self.client.add_ldev(body, no_log=True)
|
return self.client.add_ldev(body, no_log=True)
|
||||||
|
|
||||||
def create_ldev(self, size, extra_specs, pool_id, ldev_range):
|
def set_qos_specs(self, ldev, qos_specs):
|
||||||
|
self.client.set_qos_specs(ldev, qos_specs)
|
||||||
|
|
||||||
|
def create_ldev(self, size, extra_specs, pool_id, ldev_range,
|
||||||
|
qos_specs=None):
|
||||||
"""Create an LDEV of the specified size and the specified type."""
|
"""Create an LDEV of the specified size and the specified type."""
|
||||||
ldev = self._create_ldev_on_storage(
|
ldev = self._create_ldev_on_storage(
|
||||||
size, extra_specs, pool_id, ldev_range)
|
size, extra_specs, pool_id, ldev_range)
|
||||||
LOG.debug('Created logical device. (LDEV: %s)', ldev)
|
LOG.debug('Created logical device. (LDEV: %s)', ldev)
|
||||||
|
if qos_specs:
|
||||||
|
try:
|
||||||
|
self.set_qos_specs(ldev, qos_specs)
|
||||||
|
except Exception:
|
||||||
|
with excutils.save_and_reraise_exception():
|
||||||
|
try:
|
||||||
|
self.delete_ldev(ldev)
|
||||||
|
except exception.VolumeDriverException:
|
||||||
|
self.output_log(MSG.DELETE_LDEV_FAILED, ldev=ldev)
|
||||||
return ldev
|
return ldev
|
||||||
|
|
||||||
def modify_ldev_name(self, ldev, name):
|
def modify_ldev_name(self, ldev, name):
|
||||||
@ -1296,8 +1309,10 @@ class HBSDREST(common.HBSDCommon):
|
|||||||
pool_id = self.get_pool_id_of_volume(snapshot.volume)
|
pool_id = self.get_pool_id_of_volume(snapshot.volume)
|
||||||
ldev_range = self.storage_info['ldev_range']
|
ldev_range = self.storage_info['ldev_range']
|
||||||
extra_specs = self.get_volume_extra_specs(snapshot.volume)
|
extra_specs = self.get_volume_extra_specs(snapshot.volume)
|
||||||
|
qos_specs = utils.get_qos_specs_from_volume(snapshot)
|
||||||
pair['svol'] = self.create_ldev(size, extra_specs,
|
pair['svol'] = self.create_ldev(size, extra_specs,
|
||||||
pool_id, ldev_range)
|
pool_id, ldev_range,
|
||||||
|
qos_specs=qos_specs)
|
||||||
self.modify_ldev_name(pair['svol'],
|
self.modify_ldev_name(pair['svol'],
|
||||||
snapshot.id.replace("-", ""))
|
snapshot.id.replace("-", ""))
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
@ -1488,6 +1503,10 @@ class HBSDREST(common.HBSDCommon):
|
|||||||
(ldev_range and
|
(ldev_range and
|
||||||
(pvol < ldev_range[0] or ldev_range[1] < pvol))):
|
(pvol < ldev_range[0] or ldev_range[1] < pvol))):
|
||||||
extra_specs = self.get_volume_extra_specs(volume)
|
extra_specs = self.get_volume_extra_specs(volume)
|
||||||
|
if new_type:
|
||||||
|
qos_specs = utils.get_qos_specs_from_volume_type(new_type)
|
||||||
|
else:
|
||||||
|
qos_specs = utils.get_qos_specs_from_volume(volume)
|
||||||
snap_pool_id = host['capabilities']['location_info'].get(
|
snap_pool_id = host['capabilities']['location_info'].get(
|
||||||
'snap_pool_id')
|
'snap_pool_id')
|
||||||
ldev_range = host['capabilities']['location_info'].get(
|
ldev_range = host['capabilities']['location_info'].get(
|
||||||
@ -1495,7 +1514,7 @@ class HBSDREST(common.HBSDCommon):
|
|||||||
svol = self.copy_on_storage(
|
svol = self.copy_on_storage(
|
||||||
pvol, volume.size, extra_specs, new_pool_id,
|
pvol, volume.size, extra_specs, new_pool_id,
|
||||||
snap_pool_id, ldev_range,
|
snap_pool_id, ldev_range,
|
||||||
is_snapshot=False, sync=True)
|
is_snapshot=False, sync=True, qos_specs=qos_specs)
|
||||||
self.modify_ldev_name(svol, volume['id'].replace("-", ""))
|
self.modify_ldev_name(svol, volume['id'].replace("-", ""))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -1540,6 +1559,9 @@ class HBSDREST(common.HBSDCommon):
|
|||||||
|
|
||||||
def _check_specs_diff(diff, allowed_extra_specs):
|
def _check_specs_diff(diff, allowed_extra_specs):
|
||||||
for specs_key, specs_val in diff.items():
|
for specs_key, specs_val in diff.items():
|
||||||
|
if specs_key == 'qos_specs':
|
||||||
|
diff_items.append(specs_key)
|
||||||
|
continue
|
||||||
for diff_key, diff_val in specs_val.items():
|
for diff_key, diff_val in specs_val.items():
|
||||||
if (specs_key == 'extra_specs' and
|
if (specs_key == 'extra_specs' and
|
||||||
diff_key in allowed_extra_specs):
|
diff_key in allowed_extra_specs):
|
||||||
@ -1593,6 +1615,12 @@ class HBSDREST(common.HBSDCommon):
|
|||||||
|
|
||||||
self._modify_capacity_saving(ldev, new_dr_mode)
|
self._modify_capacity_saving(ldev, new_dr_mode)
|
||||||
|
|
||||||
|
if 'qos_specs' in diff_items:
|
||||||
|
old_qos_specs = self.get_qos_specs_from_ldev(ldev)
|
||||||
|
new_qos_specs = utils.get_qos_specs_from_volume_type(new_type)
|
||||||
|
if old_qos_specs != new_qos_specs:
|
||||||
|
self.change_qos_specs(ldev, old_qos_specs, new_qos_specs)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def wait_copy_completion(self, pvol, svol):
|
def wait_copy_completion(self, pvol, svol):
|
||||||
@ -1623,3 +1651,18 @@ class HBSDREST(common.HBSDCommon):
|
|||||||
'_', host[:max_host_len])
|
'_', host[:max_host_len])
|
||||||
return self.format_info['group_name_format'].format(
|
return self.format_info['group_name_format'].format(
|
||||||
host=host, wwn=wwn, ip=ip)
|
host=host, wwn=wwn, ip=ip)
|
||||||
|
|
||||||
|
def change_qos_specs(self, ldev, old_qos_specs, new_qos_specs):
|
||||||
|
delete_specs = {key: 0 for key in old_qos_specs
|
||||||
|
if key in utils.QOS_KEYS}
|
||||||
|
if delete_specs:
|
||||||
|
self.client.set_qos_specs(ldev, delete_specs)
|
||||||
|
if new_qos_specs:
|
||||||
|
self.client.set_qos_specs(ldev, new_qos_specs)
|
||||||
|
|
||||||
|
def get_qos_specs_from_ldev(self, ldev):
|
||||||
|
params = {'detailInfoType': 'qos',
|
||||||
|
'headLdevId': ldev,
|
||||||
|
'count': 1}
|
||||||
|
ldev_info = self.client.get_ldevs(params=params)[0]
|
||||||
|
return ldev_info.get('qos', {})
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Copyright (C) 2020, 2022, Hitachi, Ltd.
|
# Copyright (C) 2020, 2024, Hitachi, Ltd.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
# not use this file except in compliance with the License. You may obtain
|
# not use this file except in compliance with the License. You may obtain
|
||||||
@ -1024,6 +1024,16 @@ class RestApiClient():
|
|||||||
body = {"parameters": {"virtualLdevId": virtual_ldev_id}}
|
body = {"parameters": {"virtualLdevId": virtual_ldev_id}}
|
||||||
self._invoke(url, body=body)
|
self._invoke(url, body=body)
|
||||||
|
|
||||||
|
def set_qos_specs(self, ldev_id, qos_specs):
|
||||||
|
url = '%(url)s/ldevs/%(id)s/actions/%(action)s/invoke' % {
|
||||||
|
'url': self.object_url,
|
||||||
|
'id': ldev_id,
|
||||||
|
'action': 'set-qos',
|
||||||
|
}
|
||||||
|
for (key, value) in qos_specs.items():
|
||||||
|
body = {'parameters': {key: value}}
|
||||||
|
self._invoke(url, body=body)
|
||||||
|
|
||||||
def output_log(self, msg_enum, **kwargs):
|
def output_log(self, msg_enum, **kwargs):
|
||||||
if self.is_rep:
|
if self.is_rep:
|
||||||
return utils.output_log(
|
return utils.output_log(
|
||||||
|
@ -24,8 +24,9 @@ from oslo_utils import units
|
|||||||
|
|
||||||
from cinder import exception
|
from cinder import exception
|
||||||
from cinder import utils as cinder_utils
|
from cinder import utils as cinder_utils
|
||||||
|
from cinder.volume import volume_types
|
||||||
|
|
||||||
VERSION = '2.3.5'
|
VERSION = '2.4.0'
|
||||||
CI_WIKI_NAME = 'Hitachi_VSP_CI'
|
CI_WIKI_NAME = 'Hitachi_VSP_CI'
|
||||||
PARAM_PREFIX = 'hitachi'
|
PARAM_PREFIX = 'hitachi'
|
||||||
VENDOR_NAME = 'Hitachi'
|
VENDOR_NAME = 'Hitachi'
|
||||||
@ -58,6 +59,9 @@ PORT_ID_LENGTH = 5
|
|||||||
|
|
||||||
BUSY_MESSAGE = "Device or resource is busy."
|
BUSY_MESSAGE = "Device or resource is busy."
|
||||||
|
|
||||||
|
QOS_KEYS = ['upperIops', 'upperTransferRate',
|
||||||
|
'lowerIops', 'lowerTransferRate', 'responsePriority']
|
||||||
|
|
||||||
|
|
||||||
@enum.unique
|
@enum.unique
|
||||||
class HBSDMsg(enum.Enum):
|
class HBSDMsg(enum.Enum):
|
||||||
@ -788,6 +792,57 @@ def synchronized_on_copy_group():
|
|||||||
return wrap
|
return wrap
|
||||||
|
|
||||||
|
|
||||||
|
def get_qos_specs_from_volume(target):
|
||||||
|
"""Return a dictionary of the QoS specs of the target.
|
||||||
|
|
||||||
|
:param target: Volume or Snapshot whose QoS specs are queried.
|
||||||
|
:type target: Volume or Snapshot
|
||||||
|
:return: QoS specs.
|
||||||
|
:rtype: dict
|
||||||
|
"""
|
||||||
|
# If the target is a Volume, volume_type is volume.volume_type.
|
||||||
|
# If the target is a Snapshot, volume_type is snapshot.volume.volume_type.
|
||||||
|
# We combine these into "getattr(target, 'volume', target).volume_type)".
|
||||||
|
return get_qos_specs_from_volume_type(
|
||||||
|
getattr(target, 'volume', target).volume_type)
|
||||||
|
|
||||||
|
|
||||||
|
def get_qos_specs_from_volume_type(volume_type):
|
||||||
|
"""Return a dictionary of the QoS specs of the volume_type.
|
||||||
|
|
||||||
|
:param volume_type: VolumeType whose QoS specs are queried. This must not
|
||||||
|
be None.
|
||||||
|
:type volume_type: VolumeType
|
||||||
|
:return: QoS specs.
|
||||||
|
:rtype: dict
|
||||||
|
The following is an example of the returned value:
|
||||||
|
{'lowerTransferRate': 7,
|
||||||
|
'responsePriority': 2,
|
||||||
|
'upperIops': 456}
|
||||||
|
"""
|
||||||
|
qos = {}
|
||||||
|
specs = volume_types.get_volume_type_qos_specs(volume_type.id)['qos_specs']
|
||||||
|
# The following is an example of the specs:
|
||||||
|
# {'consumer': 'back-end',
|
||||||
|
# 'created_at': datetime.datetime(2024, 9, 2, 3, 11, 1),
|
||||||
|
# 'id': '81058c04-06eb-49d7-9199-7016785bf386',
|
||||||
|
# 'name': 'qos1',
|
||||||
|
# 'specs': {'lowerTransferRate': '7',
|
||||||
|
# 'responsePriority': '2',
|
||||||
|
# 'upperIops': '456'}}
|
||||||
|
if specs is None:
|
||||||
|
return qos
|
||||||
|
if 'consumer' in specs and specs['consumer'] not in ('back-end', 'both'):
|
||||||
|
return qos
|
||||||
|
for key in specs['specs'].keys():
|
||||||
|
if key in QOS_KEYS:
|
||||||
|
if specs['specs'][key].isdigit():
|
||||||
|
qos[key] = int(specs['specs'][key])
|
||||||
|
else:
|
||||||
|
qos[key] = specs['specs'][key]
|
||||||
|
return qos
|
||||||
|
|
||||||
|
|
||||||
DICT = '_dict'
|
DICT = '_dict'
|
||||||
CONF = '_conf'
|
CONF = '_conf'
|
||||||
|
|
||||||
|
@ -101,6 +101,7 @@ Hitachi block storage driver also supports the following additional features:
|
|||||||
* Data deduplication and compression
|
* Data deduplication and compression
|
||||||
* Port scheduler
|
* Port scheduler
|
||||||
* Port assignment using extra spec
|
* Port assignment using extra spec
|
||||||
|
* Configuring Quality of Service (QoS) settings
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
@ -376,6 +377,203 @@ If the number of pairs exceeds the maximum, copying cannot proceed normally.
|
|||||||
For information about the maximum number of copy pairs and consistency groups
|
For information about the maximum number of copy pairs and consistency groups
|
||||||
that can be created, see the `Hitachi Thin Image User Guide`_.
|
that can be created, see the `Hitachi Thin Image User Guide`_.
|
||||||
|
|
||||||
|
Configuring Quality of Service (QoS) settings
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
By configuring Quality of Service (QoS) settings, you can restrict the
|
||||||
|
I/O processing of each volume, thereby maintaining the required performance
|
||||||
|
and quality levels.
|
||||||
|
|
||||||
|
In Hitachi block storage driver, you can configure the following settings for
|
||||||
|
each volume. However, you cannot configure these settings for journal volumes.
|
||||||
|
|
||||||
|
* Throughput (IOPS, amount of data transferred in MB/s)
|
||||||
|
|
||||||
|
You can set the upper and lower limits on throughput. If an upper
|
||||||
|
limit is exceeded, I/O is suppressed. If a lower limit is not met, I/O
|
||||||
|
is adjusted so that the lower limit is met.
|
||||||
|
|
||||||
|
* Priority level of the I/O processing
|
||||||
|
|
||||||
|
You can set priority levels for the I/O processing of multiple
|
||||||
|
volumes. I/O is adjusted for faster I/O response, starting with
|
||||||
|
high-priority volumes.
|
||||||
|
|
||||||
|
**System requirements for a QoS**
|
||||||
|
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||||
|
|
||||||
|
**Storage firmware versions**
|
||||||
|
|
||||||
|
+-----------------+------------------------+
|
||||||
|
| Storage model | Firmware version |
|
||||||
|
+=================+========================+
|
||||||
|
| VSP F350, | 88-06-01 or later |
|
||||||
|
| F370, | |
|
||||||
|
| F700, | |
|
||||||
|
| F900 | |
|
||||||
|
| | |
|
||||||
|
| VSP G350, | |
|
||||||
|
| G370, | |
|
||||||
|
| G700, | |
|
||||||
|
| G900 | |
|
||||||
|
+-----------------+------------------------+
|
||||||
|
| VSP 5100, | 90-04-01 or later |
|
||||||
|
| 5500, | |
|
||||||
|
| 5100H, | |
|
||||||
|
| 5500H | |
|
||||||
|
+-----------------+------------------------+
|
||||||
|
|
||||||
|
**Storage management software**
|
||||||
|
|
||||||
|
Configuration Manager REST API version 10.2.0-00 or later is required.
|
||||||
|
|
||||||
|
**Configuring QoS settings and creating volumes**
|
||||||
|
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||||
|
|
||||||
|
Create QoS specs that define QoS settings, and then associate the QoS
|
||||||
|
specs with a volume type. You can configure QoS settings for a volume
|
||||||
|
by running the following functions with this volume type specified.
|
||||||
|
|
||||||
|
* Create Volume
|
||||||
|
* Create Snapshot
|
||||||
|
* Create Volume from Snapshot
|
||||||
|
* Create Volume from Volume (Clone)
|
||||||
|
* Consistency Group
|
||||||
|
* Generic volume group
|
||||||
|
|
||||||
|
The following example describes the procedure for configuring QoS settings
|
||||||
|
when creating a new volume using the Create Volume function.
|
||||||
|
|
||||||
|
Before you begin, Check the following information.
|
||||||
|
|
||||||
|
* QoS settings
|
||||||
|
|
||||||
|
- Upper or lower limit on throughput (IOPS, amount of data transferred
|
||||||
|
in MB/s)
|
||||||
|
- Priority level of I/O processing
|
||||||
|
|
||||||
|
* ID and name of the volume type
|
||||||
|
|
||||||
|
A volume type is needed in order to associate it with the QoS specs.
|
||||||
|
If no volume types exist, create one in advance.
|
||||||
|
|
||||||
|
**Procedure**
|
||||||
|
|
||||||
|
1. Create the QoS specs
|
||||||
|
|
||||||
|
a. If you use the cinder command:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ cinder qos-create <name-of-the-QoS-specs> [consumer=back-end] \
|
||||||
|
<name-of-a-QoS-specs-property>=<value-of-the-QoS-specs-property> \
|
||||||
|
[<name-of-a-QoS-specs-property>=<value-of-the-QoS-specs-property> ...]
|
||||||
|
|
||||||
|
\
|
||||||
|
b. If you use the openstack command:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ openstack volume qos create [--consumer back-end] \
|
||||||
|
--property \
|
||||||
|
<name-of-a-QoS-specs-property>=<value-of-the-QoS-specs-property> \
|
||||||
|
[--property \
|
||||||
|
<name-of-a-QoS-specs-property>=<value-of-the-QoS-specs-property> ...] \
|
||||||
|
<name-of-the-QoS-specs>
|
||||||
|
|
||||||
|
\
|
||||||
|
Specify a name for ``<name-of-the-QoS-specs>``.
|
||||||
|
|
||||||
|
Specify ``<name-of-a-QoS-specs-property>`` and
|
||||||
|
``<value-of-the-QoS-specs-property>`` as follows.
|
||||||
|
For details on the range of values you can specify, see the overview of
|
||||||
|
QoS operations in the `Performance Guide`_.
|
||||||
|
|
||||||
|
+--------------------+------------------------------------------+
|
||||||
|
| QoS specs property | Description |
|
||||||
|
+====================+==========================================+
|
||||||
|
| upperIops | The upper limit on IOPS. |
|
||||||
|
+--------------------+------------------------------------------+
|
||||||
|
| upperTransferRate | The upper limit on the amount of data |
|
||||||
|
| | transferred in MB/s. |
|
||||||
|
+--------------------+------------------------------------------+
|
||||||
|
| lowerIops | The lower limit on IOPS. |
|
||||||
|
+--------------------+------------------------------------------+
|
||||||
|
| lowerTransferRate | The lower limit on the amount of data |
|
||||||
|
| | transferred in MB/s. |
|
||||||
|
+--------------------+------------------------------------------+
|
||||||
|
| responsePriority | The priority level of the I/O processing.|
|
||||||
|
+--------------------+------------------------------------------+
|
||||||
|
|
||||||
|
The following is an example of running the command.
|
||||||
|
|
||||||
|
\
|
||||||
|
a. If you use the cinder command:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ cinder qos-create test_qos consumer=back-end upperIops=2000
|
||||||
|
|
||||||
|
\
|
||||||
|
b. If you use the openstack command:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ openstack volume qos create --consumer back-end \
|
||||||
|
--property upperIops=2000 test_qos
|
||||||
|
|
||||||
|
\
|
||||||
|
When you run this command, the ID of the created QoS specs is also output.
|
||||||
|
Record this ID, because you will need it in a later step.
|
||||||
|
|
||||||
|
\
|
||||||
|
|
||||||
|
2. Associate the QoS specs with a volume type.
|
||||||
|
|
||||||
|
a. If you use the cinder command:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ cinder qos-associate <ID-of-the-QoS-specs> <ID-of-the-volume-type>
|
||||||
|
|
||||||
|
\
|
||||||
|
b. If you use the openstack command:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ openstack volume qos associate <name-of-the-QoS-specs> \
|
||||||
|
<name-of-the-volume-type>
|
||||||
|
|
||||||
|
3. Specify the volume type that is associated with the QoS specs, and then
|
||||||
|
create a volume.
|
||||||
|
|
||||||
|
a. If you use the cinder command:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ cinder create --volume-type <name-of-the-volume-type> <size>
|
||||||
|
|
||||||
|
\
|
||||||
|
b. If you use the openstack command:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ openstack volume create --size <size> --type <name-of-the-volume-type> \
|
||||||
|
<name>
|
||||||
|
|
||||||
|
**Changing QoS settings**
|
||||||
|
|
||||||
|
To change the QoS settings, use the Retype function to change the volume type
|
||||||
|
to one that has different QoS specs.
|
||||||
|
|
||||||
|
You can also change a volume type for which no QoS specs are set to a volume
|
||||||
|
type for which QoS specs are set, and vice versa.
|
||||||
|
|
||||||
|
**Clearing QoS settings**
|
||||||
|
|
||||||
|
To clear the QoS settings, clear the association between the volume type and
|
||||||
|
QoS specs, and then delete the QoS specs.
|
||||||
|
|
||||||
Data deduplication and compression
|
Data deduplication and compression
|
||||||
----------------------------------
|
----------------------------------
|
||||||
|
|
||||||
@ -516,3 +714,6 @@ attach operations for each volume type.
|
|||||||
capacity-saving-function-data-deduplication-and-compression
|
capacity-saving-function-data-deduplication-and-compression
|
||||||
.. _bug #2072317:
|
.. _bug #2072317:
|
||||||
https://bugs.launchpad.net/cinder/+bug/2072317
|
https://bugs.launchpad.net/cinder/+bug/2072317
|
||||||
|
.. _Performance Guide:
|
||||||
|
https://docs.hitachivantara.com/r/en-us/svos/9.6.0/mk-98rd9019/
|
||||||
|
hitachi-performance-monitor-operations
|
||||||
|
@ -425,7 +425,7 @@ driver.dell_emc_powerflex=complete
|
|||||||
driver.dell_emc_xtremio=missing
|
driver.dell_emc_xtremio=missing
|
||||||
driver.fujitsu_eternus=missing
|
driver.fujitsu_eternus=missing
|
||||||
driver.fungible=missing
|
driver.fungible=missing
|
||||||
driver.hitachi_vsp=missing
|
driver.hitachi_vsp=complete
|
||||||
driver.hpe_3par=complete
|
driver.hpe_3par=complete
|
||||||
driver.hpe_msa=missing
|
driver.hpe_msa=missing
|
||||||
driver.hpe_nimble=missing
|
driver.hpe_nimble=missing
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Hitachi driver: Added QoS support.
|
Loading…
x
Reference in New Issue
Block a user