460 lines
16 KiB
Python
460 lines
16 KiB
Python
COPYRIGHT = """
|
|
*************************************************************
|
|
Licensed Materials - Property of IBM
|
|
|
|
OCO Source Materials
|
|
|
|
(C) Copyright IBM Corp. 2013 All Rights Reserved
|
|
*************************************************************
|
|
"""
|
|
|
|
from cinderclient.tests.v1 import fakes
|
|
from cinderclient.tests.v1.test_volumes import VolumesTest
|
|
from cinderclient.tests.v1.test_types import TypesTest
|
|
from cinderclient.tests import utils
|
|
from cinderclient.v1.volumes import Volume
|
|
from cinderclient.v1.volume_types import VolumeType
|
|
from cinderclient.v1.volume_types import VolumeTypeManager
|
|
from powervc.common.client.extensions import cinder as ext_cinder
|
|
from powervc.common.client import delegate
|
|
from powervc.common import utils as commonutils
|
|
|
|
import mock
|
|
import sys
|
|
|
|
|
|
"""
|
|
This class similarly extend the current cinder client test cases
|
|
and also provided are examples of how someone can override and existing
|
|
method in the event we need to test something unique to powerVC.
|
|
|
|
The current methods that are overridden expect the same results as the base
|
|
class test cases and are only provided for example.
|
|
|
|
For specific PowerVC data model, just override the parent fake data
|
|
structure and corresponding testcase methods logic that could verify
|
|
the functions.
|
|
|
|
To run the testcases, alternatively:
|
|
1. Right click the TestCinderClient.py --> Run As --> Python unit-test
|
|
or
|
|
2. Refer to this link for detail UT running information:
|
|
https://jazz04.rchland.ibm.com:9443/jazz/service/ +
|
|
com.ibm.team.workitem.common.internal.rest.IAttachmentRestService/ +
|
|
itemName/com.ibm.team.workitem.Attachment/67843
|
|
|
|
All the testcases should be run successfully.
|
|
"""
|
|
|
|
|
|
class PVCFakeClient(fakes.FakeClient):
|
|
|
|
"""
|
|
This PVCFakeClient class extends the current cinder FakeClient,
|
|
and pvccinderclient.CinderClient.
|
|
aiming to set the self client variable to PVCFakeHTTPClient
|
|
"""
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
fakes.FakeClient.__init__(self, *args, **kwargs)
|
|
self.client = PVCFakeHTTPClient(**kwargs)
|
|
sys.modules['powervc.common.client.factory'] = mock.MagicMock()
|
|
|
|
|
|
class PVCFakeHTTPClient(fakes.FakeHTTPClient):
|
|
|
|
"""
|
|
This PVCFakeHTTPClient class extends the current cinder FakeHTTPClient.
|
|
For all the HTTP requests in this class, it returns a fake json data
|
|
as specified beforehand instead of requesting to a real environment.
|
|
Ex, to test if json data from powerVC volume RESTAPI:
|
|
1. Add expected powerVC volumes json raw data into
|
|
get_volumes_detail() method
|
|
2. Add get_volumes_{volume_id} method to return the volume
|
|
3. Add post_volumes_{volume_id}_action to handle post logic
|
|
4. Add testcase and new added methods will be called
|
|
"""
|
|
|
|
def __init__(self, **kwargs):
|
|
fakes.FakeHTTPClient.__init__(self, **kwargs)
|
|
|
|
def get_volumes_pvcvolume(self, **kw):
|
|
r = {'volume': self.get_volumes_detail()[2]['volumes'][1]}
|
|
return (200, {}, r)
|
|
|
|
def get_volumes_detail(self, **kw):
|
|
"""
|
|
Override the parent method to a new powerVC specified volume,
|
|
Here is the same structure as OpenStack one for example.
|
|
"""
|
|
return (200, {}, {"volumes": [
|
|
{'id': 1234,
|
|
'name': 'sample-volume for cinder',
|
|
'attachments': [{'server_id': 12234}]},
|
|
{'id': 'pvcvolume',
|
|
'name': 'pvc sample-volume for cinder',
|
|
'attachments': [{'server_id': 54321}]}
|
|
]})
|
|
|
|
def post_volumes_pvcvolume_action(self, body, **kw):
|
|
"""
|
|
Add this method to handle powerVC volume post actions
|
|
Here is the same logic as OpenStack one for example.
|
|
"""
|
|
_body = None
|
|
resp = 202
|
|
assert len(list(body.keys())) == 1
|
|
action = list(body.keys())[0]
|
|
if action == 'os-attach':
|
|
assert sorted(list(body[action])) == ['instance_uuid',
|
|
'mode',
|
|
'mountpoint']
|
|
elif action == 'os-detach':
|
|
assert body[action] is None
|
|
elif action == 'os-reserve':
|
|
assert body[action] is None
|
|
elif action == 'os-unreserve':
|
|
assert body[action] is None
|
|
elif action == 'os-initialize_connection':
|
|
assert list(body[action].keys()) == ['connector']
|
|
return (202, {}, {'connection_info': 'foos'})
|
|
elif action == 'os-terminate_connection':
|
|
assert list(body[action].keys()) == ['connector']
|
|
elif action == 'os-begin_detaching':
|
|
assert body[action] is None
|
|
elif action == 'os-roll_detaching':
|
|
assert body[action] is None
|
|
elif action == 'os-reset_status':
|
|
assert 'status' in body[action]
|
|
else:
|
|
raise AssertionError("Unexpected action: %s" % action)
|
|
return (resp, {}, _body)
|
|
|
|
def get_storage_providers_2(self, **kw):
|
|
"""
|
|
To get a fake detail storage_providers
|
|
"""
|
|
return (200, {}, {"storage_provider":
|
|
{
|
|
"backend_type": "svc",
|
|
"volume_count": "null",
|
|
"service": {
|
|
"host_display_name": "shared_v7000_1",
|
|
"host": "shared_v7000_1",
|
|
"id": 4
|
|
},
|
|
"backend_id": "00000200A0204C30",
|
|
"health_status": {
|
|
"health_value": "OK"
|
|
},
|
|
"free_capacity_gb": 873.5,
|
|
"total_capacity_gb": 1115.5,
|
|
"storage_hostname": "shared_v7000_1",
|
|
"id": 2,
|
|
"backend_state": "running"
|
|
}})
|
|
|
|
def get_storage_providers_detail(self, **kw):
|
|
"""
|
|
To return a fake detail storage_providers
|
|
"""
|
|
return (200, {}, {"storage_providers": [
|
|
{
|
|
"backend_type": "svc",
|
|
"volume_count": "null",
|
|
"service": {
|
|
"host_display_name": "shared_v7000_1",
|
|
"host": "shared_v7000_1",
|
|
"id": 4
|
|
},
|
|
"backend_id": "00000200A0204C30",
|
|
"health_status": {
|
|
"health_value": "OK"
|
|
},
|
|
"free_capacity_gb": 873.5,
|
|
"total_capacity_gb": 1115.5,
|
|
"storage_hostname": "shared_v7000_1",
|
|
"id": 2,
|
|
"backend_state": "running"
|
|
},
|
|
{
|
|
"backend_type": "fc",
|
|
"volume_count": "null",
|
|
"service": {
|
|
"host_display_name": "shared_v7000_1",
|
|
"host": "shared_v7000_1",
|
|
"id": 4
|
|
},
|
|
"backend_id": "00000200A0204C31",
|
|
"health_status": {
|
|
"health_value": "OK"
|
|
},
|
|
"free_capacity_gb": 73.5,
|
|
"total_capacity_gb": 115.5,
|
|
"storage_hostname": "shared_v7000_2",
|
|
"id": 3,
|
|
"backend_state": "running"
|
|
}
|
|
]})
|
|
|
|
def get_types(self, **kw):
|
|
return (200, {}, {
|
|
"volume_types": [
|
|
{
|
|
"extra_specs": {
|
|
"drivers:storage_pool": "P-NGP01-pool",
|
|
"capabilities:volume_backend_name": "shared_v7000_1",
|
|
"drivers:rsize": "-1"
|
|
},
|
|
"name": "shared_v7000_1-default",
|
|
"id": "6627888e-9f59-4996-8c22-5d528c3273f0"
|
|
},
|
|
{
|
|
"extra_specs": {},
|
|
"name": "dm-crypt",
|
|
"id": "a3ae95f6-4aab-4446-b1d2-0fc2f60a89bb"
|
|
},
|
|
{
|
|
"extra_specs": {},
|
|
"name": "LUKS",
|
|
"id": "291f81a2-591b-4164-b2b2-829abc935573"
|
|
}
|
|
]
|
|
})
|
|
|
|
|
|
class PVCCinderVolumesTest(VolumesTest):
|
|
|
|
"""
|
|
This PVCCinderVolumesTest class extends the current cinder
|
|
VolumesTest class to provide volume related UT cases.
|
|
"""
|
|
|
|
volume_list = [
|
|
{
|
|
'id': 1234,
|
|
'name': 'sample-volume for cinder',
|
|
'attachments': [{'server_id': 12234}]},
|
|
{
|
|
'id': 'pvcvolume',
|
|
'name': 'pvc sample-volume for cinder',
|
|
'attachments': [{'server_id': 54321}]
|
|
}]
|
|
|
|
def setUp(self):
|
|
super(PVCCinderVolumesTest, self).setUp()
|
|
# get cinder client
|
|
cinder_fakeclient = PVCFakeClient('r', 'p')
|
|
# delegate to nova extension class
|
|
cinder_client = delegate.new_composite_deletgate(
|
|
[ext_cinder.Client(cinder_fakeclient), cinder_fakeclient])
|
|
self.cs = cinder_client
|
|
|
|
def tearDown(self):
|
|
super(PVCCinderVolumesTest, self).tearDown()
|
|
|
|
def test_pvcvolume_attach(self):
|
|
"""
|
|
Add this method to test if powerVC volume attach functions
|
|
Here is the same logic as OpenStack for example.
|
|
"""
|
|
v = self.cs.volumes.get('pvcvolume')
|
|
self.cs.volumes.attach(v, 1, '/dev/vdc')
|
|
self.cs.assert_called('POST',
|
|
'/volumes/pvcvolume/action')
|
|
|
|
def test_list_all_volumes(self):
|
|
resluts = self.cs.volumes.list_all_volumes()
|
|
|
|
self.cs.assert_called('GET', '/volumes/detail')
|
|
self.assertEqual(resluts[0].id, 1234)
|
|
self.assertEqual(resluts[1].name, 'pvc sample-volume for cinder')
|
|
|
|
def test_list_volumes_1(self):
|
|
returnvalues = [Volume(self, res, loaded=True)
|
|
for res in self.volume_list if res]
|
|
commonutils.get_utils().get_multi_scg_accessible_volumes = \
|
|
mock.MagicMock(return_value=returnvalues)
|
|
result = self.cs.volumes.list()
|
|
|
|
self.assertEquals(result[0].id, 1234)
|
|
self.assertEquals(result[1].name, "pvc sample-volume for cinder")
|
|
|
|
def test_list_volumes_2(self):
|
|
returnvalues = [Volume(self, res, loaded=True)
|
|
for res in self.volume_list if res]
|
|
commonutils.get_utils().get_scg_accessible_volumes = \
|
|
mock.MagicMock(return_value=returnvalues)
|
|
|
|
result = self.cs.volumes.list(True, None, 'SCGUUID', None)
|
|
self.assertEquals(result[0].name, "sample-volume for cinder")
|
|
|
|
|
|
class PVCCinderTypesTest(TypesTest):
|
|
|
|
"""
|
|
This PVCCinderTypesTest class extends the current cinder
|
|
TypesTest class to provide volume Type related UT cases.
|
|
"""
|
|
volumes_type_list = [
|
|
{
|
|
"extra_specs": {
|
|
"drivers:storage_pool": "P-NGP01-pool",
|
|
"capabilities:volume_backend_name": "shared_v7000_1",
|
|
"drivers:rsize": "-1"
|
|
},
|
|
"name": "shared_v7000_1-default",
|
|
"id": "6627888e-9f59-4996-8c22-5d528c3273f"
|
|
},
|
|
{
|
|
"extra_specs": {},
|
|
"name": "dm-crypt",
|
|
"id": "a3ae95f6-4aab-4446-b1d2-0fc2f60a89b"
|
|
},
|
|
{
|
|
"extra_specs": {},
|
|
"name": "LUKS",
|
|
"id": "291f81a2-591b-4164-b2b2-829abc93557"
|
|
}]
|
|
|
|
def setUp(self):
|
|
super(PVCCinderTypesTest, self).setUp()
|
|
# get cinder client
|
|
cinder_fakeclient = PVCFakeClient('r', 'p')
|
|
# delegate to nova extension class
|
|
cinder_client = delegate.new_composite_deletgate(
|
|
[ext_cinder.Client(cinder_fakeclient), cinder_fakeclient])
|
|
self.cs = cinder_client
|
|
|
|
def tearDown(self):
|
|
super(PVCCinderTypesTest, self).tearDown()
|
|
|
|
def test_list_all_storage_templates(self):
|
|
|
|
reslut = self.cs.volume_types.list_all_storage_templates()
|
|
|
|
self.assertEqual(reslut[0].name, "shared_v7000_1-default")
|
|
|
|
def test_list_storage_templates_1(self):
|
|
returnvalues = [VolumeType(VolumeTypeManager, res, loaded=True)
|
|
for res in self.volumes_type_list if res]
|
|
|
|
commonutils.get_utils().get_multi_scg_accessible_storage_templates = \
|
|
mock.MagicMock(return_value=returnvalues)
|
|
result = self.cs.volume_types.list()
|
|
|
|
self.assertEquals(result[0].id, "6627888e-9f59-4996-8c22-5d528c3273f")
|
|
self.assertEquals(result[1].name, "dm-crypt")
|
|
self.assertEquals(result[2].name, "LUKS")
|
|
|
|
def test_list_storage_templates_2(self):
|
|
data = self.volumes_type_list[2]
|
|
returnvalues = [VolumeType(VolumeTypeManager, res, loaded=True)
|
|
for res in [data] if res]
|
|
|
|
commonutils.get_utils().get_scg_accessible_storage_templates = \
|
|
mock.MagicMock(return_value=returnvalues)
|
|
result = self.cs.volume_types.list("SCGUUID", None)
|
|
|
|
self.assertEquals(result[0].name, "LUKS")
|
|
|
|
|
|
class PVCStorageProvidersTest(utils.TestCase):
|
|
|
|
"""
|
|
Class PVCStorageProvidersTest is used to provide
|
|
Storage Providers related UT cases.
|
|
"""
|
|
expected_sp = [
|
|
dict(
|
|
backend_type="svc",
|
|
volume_count="null",
|
|
service=dict(
|
|
host_display_name="shared_v7000_1",
|
|
host="shared_v7000_1",
|
|
id=4),
|
|
backend_id="00000200A0204C30",
|
|
health_status=dict(health_value="OK"),
|
|
free_capacity_gb=873.5,
|
|
total_capacity_gb=1115.5,
|
|
storage_hostname="shared_v7000_1",
|
|
id=2,
|
|
backend_state="running",
|
|
storage_type="fc")]
|
|
|
|
def setUp(self):
|
|
super(PVCStorageProvidersTest, self).setUp()
|
|
# get cinder client
|
|
cinder_fakeclient = PVCFakeClient('r', 'p')
|
|
# delegate to nova extension class
|
|
cinder_client = delegate.new_composite_deletgate(
|
|
[ext_cinder.Client(cinder_fakeclient), cinder_fakeclient])
|
|
self.cs = cinder_client
|
|
|
|
def tearDown(self):
|
|
super(PVCStorageProvidersTest, self).tearDown()
|
|
|
|
def compare_to_expected(self, expected, hyper):
|
|
for key, value in expected.items():
|
|
self.assertEqual(getattr(hyper, key), value)
|
|
|
|
def test_get_detail_SPs(self):
|
|
expected = [
|
|
dict(id=2,
|
|
backend_type="svc",
|
|
backend_id="00000200A0204C30",
|
|
free_capacity_gb=873.5,
|
|
total_capacity_gb=1115.5,
|
|
storage_hostname="shared_v7000_1",
|
|
backend_state="running"),
|
|
dict(id=3,
|
|
backend_type="fc",
|
|
backend_id="00000200A0204C31",
|
|
free_capacity_gb=73.5,
|
|
total_capacity_gb=115.5,
|
|
storage_hostname="shared_v7000_2",
|
|
backend_state="running")]
|
|
|
|
result = self.cs.storage_providers.list_all_providers()
|
|
self.cs.assert_called('GET', '/storage-providers/detail')
|
|
|
|
for idx, hyper in enumerate(result):
|
|
self.compare_to_expected(expected[idx], hyper)
|
|
|
|
def test_get_storage_provider(self):
|
|
expected = dict(id=2,
|
|
backend_type="svc",
|
|
backend_id="00000200A0204C30",
|
|
free_capacity_gb=873.5,
|
|
total_capacity_gb=1115.5,
|
|
storage_hostname="shared_v7000_1",
|
|
backend_state="running")
|
|
|
|
result = self.cs.storage_providers.get(2)
|
|
self.cs.assert_called('GET',
|
|
'/storage-providers/2')
|
|
|
|
self.compare_to_expected(expected, result)
|
|
|
|
def test_list_SP_1(self):
|
|
expected = self.expected_sp
|
|
returnvalue = [ext_cinder.StorageProvider(None, expected[0], True)]
|
|
|
|
commonutils.get_utils().get_scg_accessible_storage_providers = \
|
|
mock.MagicMock(return_value=returnvalue)
|
|
result = self.cs.storage_providers.list(True, None, "SCGUUID", None)
|
|
|
|
for idx, hyper in enumerate(result):
|
|
self.compare_to_expected(expected[idx], hyper)
|
|
|
|
def test_list_SP_2(self):
|
|
expected = self.expected_sp
|
|
returnvalue = [ext_cinder.StorageProvider(None, expected[0], True)]
|
|
|
|
commonutils.get_utils().get_multi_scg_accessible_storage_providers = \
|
|
mock.MagicMock(return_value=returnvalue)
|
|
result = self.cs.storage_providers.list()
|
|
|
|
for idx, hyper in enumerate(result):
|
|
self.compare_to_expected(expected[idx], hyper)
|