manila/manila/tests/share/drivers/dell_emc/plugins/unity/res_mock.py

374 lines
13 KiB
Python

# Copyright (c) 2016 EMC Corporation.
# All Rights Reserved.
#
# 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
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from unittest import mock
from oslo_config import cfg
from oslo_log import log
from manila.share import configuration as conf
from manila.share.drivers.dell_emc.plugins.unity import client
from manila.share.drivers.dell_emc.plugins.unity import connection
from manila.tests.db import fakes as db_fakes
from manila.tests import fake_share
from manila.tests.share.drivers.dell_emc.plugins.unity import fake_exceptions
from manila.tests.share.drivers.dell_emc.plugins.unity import utils
client.storops_ex = fake_exceptions
connection.storops_ex = fake_exceptions
LOG = log.getLogger(__name__)
SYMBOL_TYPE = '_type'
SYMBOL_PROPERTIES = '_properties'
SYMBOL_METHODS = '_methods'
SYMBOL_SIDE_EFFECT = '_side_effect'
SYMBOL_RAISE = '_raise'
CONF = cfg.CONF
def _has_side_effect(node):
return isinstance(node, dict) and SYMBOL_SIDE_EFFECT in node
def _has_raise(node):
return isinstance(node, dict) and SYMBOL_RAISE in node
def fake_share_server(**kwargs):
share_server = {
'instance_id': 'fake_instance_id',
'backend_details': {},
}
share_server.update(kwargs)
return db_fakes.FakeModel(share_server)
def fake_network_info(**kwargs):
network_info = {
'id': 'fake_net_id',
'name': 'net_name',
'subnet': [],
}
network_info.update(kwargs)
return network_info
def fake_server_detail(**kwargs):
server_detail = {
'share_server_name': 'fake_server_name',
}
server_detail.update(kwargs)
return server_detail
def fake_security_services(**kwargs):
return kwargs['services']
def fake_access(**kwargs):
access = {}
access.update(kwargs)
return access
class FakeEMCShareDriver(object):
def __init__(self, dhss=None):
if dhss in (True, False):
CONF.set_default('driver_handles_share_servers', dhss)
self.configuration = conf.Configuration(None)
self.configuration.emc_share_backend = 'unity'
self.configuration.emc_nas_server = '192.168.1.1'
self.configuration.emc_nas_login = 'fake_user'
self.configuration.emc_nas_password = 'fake_password'
self.configuration.share_backend_name = 'EMC_NAS_Storage'
self.configuration.vnx_server_meta_pool = 'nas_server_pool'
self.configuration.unity_server_meta_pool = 'nas_server_pool'
self.configuration.local_conf.max_over_subscription_ratio = 20
class FakeEMCShareDriverIPv6(object):
def __init__(self, dhss=None):
if dhss in (True, False):
CONF.set_default('driver_handles_share_servers', dhss)
self.configuration = conf.Configuration(None)
self.configuration.emc_share_backend = 'unity'
self.configuration.emc_nas_server = 'fa27:2a95:e734:0:0:0:0:01'
self.configuration.emc_nas_login = 'fake_user'
self.configuration.emc_nas_password = 'fake_password'
self.configuration.share_backend_name = 'EMC_NAS_Storage'
self.configuration.vnx_server_meta_pool = 'nas_server_pool'
self.configuration.unity_server_meta_pool = 'nas_server_pool'
self.configuration.local_conf.max_over_subscription_ratio = 20
STATS = dict(
share_backend_name='Unity',
vendor_name='EMC',
storage_protocol='NFS_CIFS',
driver_version='2.0.0,',
pools=[],
)
class DriverResourceMock(dict):
fake_func_mapping = {}
def __init__(self, yaml_file):
yaml_dict = utils.load_yaml(yaml_file)
if isinstance(yaml_dict, dict):
for name, body in yaml_dict.items():
if isinstance(body, dict):
props = body[SYMBOL_PROPERTIES]
if isinstance(props, dict):
for prop_name, prop_value in props.items():
if isinstance(prop_value, dict) and prop_value:
# get the first key as the convert function
func_name = list(prop_value.keys())[0]
if func_name.startswith('_'):
func = getattr(self, func_name)
props[prop_name] = (
func(**prop_value[func_name]))
if body[SYMBOL_TYPE] in self.fake_func_mapping:
self[name] = (
self.fake_func_mapping[body[SYMBOL_TYPE]](**props))
class ManilaResourceMock(DriverResourceMock):
fake_func_mapping = {
'share': fake_share.fake_share,
'snapshot': fake_share.fake_snapshot,
'network_info': fake_network_info,
'share_server': fake_share_server,
'server_detail': fake_server_detail,
'security_services': fake_security_services,
'access': fake_access,
}
def __init__(self, yaml_file):
super(ManilaResourceMock, self).__init__(yaml_file)
class StorageObjectMock(object):
PROPS = 'props'
def __init__(self, yaml_dict):
self.__dict__[StorageObjectMock.PROPS] = {}
props = yaml_dict.get(SYMBOL_PROPERTIES, None)
if props:
for k, v in props.items():
setattr(self, k, StoragePropertyMock(k, v)())
methods = yaml_dict.get(SYMBOL_METHODS, None)
if methods:
for k, v in methods.items():
setattr(self, k, StorageMethodMock(k, v))
def __setattr__(self, key, value):
self.__dict__[StorageObjectMock.PROPS][key] = value
def __getattr__(self, item):
try:
super(StorageObjectMock, self).__getattr__(item)
except AttributeError:
return self.__dict__[StorageObjectMock.PROPS][item]
except KeyError:
raise KeyError('No such method or property for mock object.')
class StoragePropertyMock(mock.PropertyMock):
def __init__(self, name, property_body):
return_value = property_body
side_effect = None
# only support return_value and side_effect for property
if _has_side_effect(property_body):
side_effect = property_body[SYMBOL_SIDE_EFFECT]
return_value = None
if side_effect:
super(StoragePropertyMock, self).__init__(
name=name,
side_effect=side_effect)
elif return_value:
super(StoragePropertyMock, self).__init__(
name=name,
return_value=_build_mock_object(return_value))
else:
super(StoragePropertyMock, self).__init__(
name=name,
return_value=return_value)
class StorageMethodMock(mock.Mock):
def __init__(self, name, method_body):
return_value = method_body
exception = None
side_effect = None
# support return_value, side_effect and exception for method
if _has_side_effect(method_body) or _has_raise(method_body):
exception = method_body.get(SYMBOL_RAISE, None)
side_effect = method_body.get(SYMBOL_SIDE_EFFECT, None)
return_value = None
if exception:
if isinstance(exception, dict) and exception:
ex_name = list(exception.keys())[0]
ex = getattr(fake_exceptions, ex_name)
super(StorageMethodMock, self).__init__(
name=name,
side_effect=ex(exception[ex_name]))
elif side_effect:
super(StorageMethodMock, self).__init__(
name=name,
side_effect=_build_mock_object(side_effect))
elif return_value is not None:
super(StorageMethodMock, self).__init__(
name=name,
return_value=_build_mock_object(return_value))
else:
super(StorageMethodMock, self).__init__(
name=name, return_value=None)
class StorageResourceMock(dict):
def __init__(self, yaml_file):
yaml_dict = utils.load_yaml(yaml_file)
if isinstance(yaml_dict, dict):
for section, sec_body in yaml_dict.items():
self[section] = {}
if isinstance(sec_body, dict):
for obj_name, obj_body in sec_body.items():
self[section][obj_name] = _build_mock_object(obj_body)
def _is_mock_object(yaml_info):
return (isinstance(yaml_info, dict) and
(SYMBOL_PROPERTIES in yaml_info or SYMBOL_METHODS in yaml_info))
def _build_mock_object(yaml_dict):
if _is_mock_object(yaml_dict):
return StorageObjectMock(yaml_dict)
elif isinstance(yaml_dict, dict):
return {k: _build_mock_object(v) for k, v in yaml_dict.items()}
elif isinstance(yaml_dict, list):
return [_build_mock_object(each) for each in yaml_dict]
else:
return yaml_dict
manila_res = ManilaResourceMock('mocked_manila.yaml')
unity_res = StorageResourceMock('mocked_unity.yaml')
STORAGE_RES_MAPPING = {
'TestClient': unity_res,
'TestConnection': unity_res,
'TestConnectionDHSSFalse': unity_res,
}
def mock_input(resource):
def inner_dec(func):
def decorated(cls, *args, **kwargs):
if cls._testMethodName in resource:
storage_res = resource[cls._testMethodName]
return func(cls, storage_res, *args, **kwargs)
return decorated
return inner_dec
mock_client_input = mock_input(unity_res)
def patch_client(func):
def client_decorator(cls, *args, **kwargs):
storage_res = {}
if func.__name__ in STORAGE_RES_MAPPING[cls.__class__.__name__]:
storage_res = (
STORAGE_RES_MAPPING[cls.__class__.__name__][func.__name__])
with utils.patch_system as patched_system:
if 'unity' in storage_res:
patched_system.return_value = storage_res['unity']
_client = client.UnityClient(host='fake_host',
username='fake_user',
password='fake_passwd')
return func(cls, _client, *args, **kwargs)
return client_decorator
def mock_driver_input(resource):
def inner_dec(func):
def decorated(cls, *args, **kwargs):
return func(cls, resource, *args, **kwargs)
return decorated
return inner_dec
mock_manila_input = mock_driver_input(manila_res)
def patch_connection_init(func):
def connection_decorator(cls, *args, **kwargs):
storage_res = {}
if func.__name__ in STORAGE_RES_MAPPING[cls.__class__.__name__]:
storage_res = (
STORAGE_RES_MAPPING[cls.__class__.__name__][func.__name__])
with utils.patch_system as patched_system:
if 'unity' in storage_res:
patched_system.return_value = storage_res['unity']
conn = connection.UnityStorageConnection(LOG)
return func(cls, conn, *args, **kwargs)
return connection_decorator
def do_connection_connect(conn, res):
conn.config = None
conn.client = client.UnityClient(host='fake_host',
username='fake_user',
password='fake_passwd')
conn.pool_conf = ['pool_1', 'pool_2']
conn.pool_set = set(['pool_1', 'pool_2'])
conn.reserved_percentage = 0
conn.max_over_subscription_ratio = 20
conn.port_set = set(['spa_eth1', 'spa_eth2'])
conn.nas_server_pool = StorageObjectMock(res['nas_server_pool'])
conn.storage_processor = StorageObjectMock(res['sp_a'])
def patch_connection(func):
def connection_decorator(cls, *args, **kwargs):
storage_res = {}
if func.__name__ in STORAGE_RES_MAPPING[cls.__class__.__name__]:
storage_res = (
STORAGE_RES_MAPPING[cls.__class__.__name__][func.__name__])
with utils.patch_system as patched_system:
conn = connection.UnityStorageConnection(LOG)
if 'unity' in storage_res:
patched_system.return_value = storage_res['unity']
do_connection_connect(
conn, STORAGE_RES_MAPPING[cls.__class__.__name__])
return func(cls, conn, *args, **kwargs)
return connection_decorator