Coverage for manila/tests/share/drivers/dell_emc/plugins/unity/res_mock.py: 95%
226 statements
« prev ^ index » next coverage.py v7.11.0, created at 2026-02-18 22:19 +0000
« prev ^ index » next coverage.py v7.11.0, created at 2026-02-18 22:19 +0000
1# Copyright (c) 2016 EMC Corporation.
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
16from unittest import mock
18from oslo_config import cfg
19from oslo_log import log
21from manila.share import configuration as conf
22from manila.share.drivers.dell_emc.plugins.unity import client
23from manila.share.drivers.dell_emc.plugins.unity import connection
24from manila.tests.db import fakes as db_fakes
25from manila.tests import fake_share
26from manila.tests.share.drivers.dell_emc.plugins.unity import fake_exceptions
27from manila.tests.share.drivers.dell_emc.plugins.unity import utils
29client.storops_ex = fake_exceptions
30connection.storops_ex = fake_exceptions
32LOG = log.getLogger(__name__)
34SYMBOL_TYPE = '_type'
35SYMBOL_PROPERTIES = '_properties'
36SYMBOL_METHODS = '_methods'
37SYMBOL_SIDE_EFFECT = '_side_effect'
38SYMBOL_RAISE = '_raise'
39CONF = cfg.CONF
42def _has_side_effect(node):
43 return isinstance(node, dict) and SYMBOL_SIDE_EFFECT in node
46def _has_raise(node):
47 return isinstance(node, dict) and SYMBOL_RAISE in node
50def fake_share_server(**kwargs):
51 share_server = {
52 'instance_id': 'fake_instance_id',
53 'backend_details': {},
54 }
56 share_server.update(kwargs)
58 return db_fakes.FakeModel(share_server)
61def fake_network_info(**kwargs):
62 network_info = {
63 'id': 'fake_net_id',
64 'name': 'net_name',
65 'subnet': [],
66 }
67 network_info.update(kwargs)
68 return network_info
71def fake_server_detail(**kwargs):
72 server_detail = {
73 'share_server_name': 'fake_server_name',
74 }
75 server_detail.update(kwargs)
76 return server_detail
79def fake_security_services(**kwargs):
80 return kwargs['services']
83def fake_access(**kwargs):
84 access = {}
85 access.update(kwargs)
86 return access
89class FakeEMCShareDriver(object):
90 def __init__(self, dhss=None):
91 if dhss in (True, False):
92 CONF.set_default('driver_handles_share_servers', dhss)
93 self.configuration = conf.Configuration(None)
94 self.configuration.emc_share_backend = 'unity'
95 self.configuration.emc_nas_server = '192.168.1.1'
96 self.configuration.emc_nas_login = 'fake_user'
97 self.configuration.emc_nas_password = 'fake_password'
98 self.configuration.share_backend_name = 'EMC_NAS_Storage'
99 self.configuration.vnx_server_meta_pool = 'nas_server_pool'
100 self.configuration.unity_server_meta_pool = 'nas_server_pool'
101 self.configuration.local_conf.max_over_subscription_ratio = 20
104class FakeEMCShareDriverIPv6(object):
105 def __init__(self, dhss=None):
106 if dhss in (True, False): 106 ↛ 108line 106 didn't jump to line 108 because the condition on line 106 was always true
107 CONF.set_default('driver_handles_share_servers', dhss)
108 self.configuration = conf.Configuration(None)
109 self.configuration.emc_share_backend = 'unity'
110 self.configuration.emc_nas_server = 'fa27:2a95:e734:0:0:0:0:01'
111 self.configuration.emc_nas_login = 'fake_user'
112 self.configuration.emc_nas_password = 'fake_password'
113 self.configuration.share_backend_name = 'EMC_NAS_Storage'
114 self.configuration.vnx_server_meta_pool = 'nas_server_pool'
115 self.configuration.unity_server_meta_pool = 'nas_server_pool'
116 self.configuration.local_conf.max_over_subscription_ratio = 20
119STATS = dict(
120 share_backend_name='Unity',
121 vendor_name='EMC',
122 storage_protocol='NFS_CIFS',
123 driver_version='2.0.0,',
124 pools=[],
125)
128class DriverResourceMock(dict):
129 fake_func_mapping = {}
131 def __init__(self, yaml_file):
132 yaml_dict = utils.load_yaml(yaml_file)
133 if isinstance(yaml_dict, dict): 133 ↛ exitline 133 didn't return from function '__init__' because the condition on line 133 was always true
134 for name, body in yaml_dict.items():
135 if isinstance(body, dict): 135 ↛ 134line 135 didn't jump to line 134 because the condition on line 135 was always true
136 props = body[SYMBOL_PROPERTIES]
137 if isinstance(props, dict):
138 for prop_name, prop_value in props.items():
139 if isinstance(prop_value, dict) and prop_value:
140 # get the first key as the convert function
141 func_name = list(prop_value.keys())[0]
142 if func_name.startswith('_'): 142 ↛ 143line 142 didn't jump to line 143 because the condition on line 142 was never true
143 func = getattr(self, func_name)
144 props[prop_name] = (
145 func(**prop_value[func_name]))
146 if body[SYMBOL_TYPE] in self.fake_func_mapping:
147 self[name] = (
148 self.fake_func_mapping[body[SYMBOL_TYPE]](**props))
151class ManilaResourceMock(DriverResourceMock):
152 fake_func_mapping = {
153 'share': fake_share.fake_share,
154 'snapshot': fake_share.fake_snapshot,
155 'network_info': fake_network_info,
156 'share_server': fake_share_server,
157 'server_detail': fake_server_detail,
158 'security_services': fake_security_services,
159 'access': fake_access,
160 }
162 def __init__(self, yaml_file):
163 super(ManilaResourceMock, self).__init__(yaml_file)
166class StorageObjectMock(object):
167 PROPS = 'props'
169 def __init__(self, yaml_dict):
170 self.__dict__[StorageObjectMock.PROPS] = {}
171 props = yaml_dict.get(SYMBOL_PROPERTIES, None)
172 if props:
173 for k, v in props.items():
174 setattr(self, k, StoragePropertyMock(k, v)())
176 methods = yaml_dict.get(SYMBOL_METHODS, None)
177 if methods:
178 for k, v in methods.items():
179 setattr(self, k, StorageMethodMock(k, v))
181 def __setattr__(self, key, value):
182 self.__dict__[StorageObjectMock.PROPS][key] = value
184 def __getattr__(self, item):
185 try:
186 super(StorageObjectMock, self).__getattr__(item)
187 except AttributeError:
188 return self.__dict__[StorageObjectMock.PROPS][item]
189 except KeyError:
190 raise KeyError('No such method or property for mock object.')
193class StoragePropertyMock(mock.PropertyMock):
194 def __init__(self, name, property_body):
195 return_value = property_body
196 side_effect = None
198 # only support return_value and side_effect for property
199 if _has_side_effect(property_body): 199 ↛ 200line 199 didn't jump to line 200 because the condition on line 199 was never true
200 side_effect = property_body[SYMBOL_SIDE_EFFECT]
201 return_value = None
203 if side_effect: 203 ↛ 204line 203 didn't jump to line 204 because the condition on line 203 was never true
204 super(StoragePropertyMock, self).__init__(
205 name=name,
206 side_effect=side_effect)
207 elif return_value:
208 super(StoragePropertyMock, self).__init__(
209 name=name,
210 return_value=_build_mock_object(return_value))
211 else:
212 super(StoragePropertyMock, self).__init__(
213 name=name,
214 return_value=return_value)
217class StorageMethodMock(mock.Mock):
218 def __init__(self, name, method_body):
219 return_value = method_body
220 exception = None
221 side_effect = None
223 # support return_value, side_effect and exception for method
224 if _has_side_effect(method_body) or _has_raise(method_body):
225 exception = method_body.get(SYMBOL_RAISE, None)
226 side_effect = method_body.get(SYMBOL_SIDE_EFFECT, None)
227 return_value = None
229 if exception:
230 if isinstance(exception, dict) and exception: 230 ↛ 233line 230 didn't jump to line 233 because the condition on line 230 was always true
231 ex_name = list(exception.keys())[0]
232 ex = getattr(fake_exceptions, ex_name)
233 super(StorageMethodMock, self).__init__(
234 name=name,
235 side_effect=ex(exception[ex_name]))
236 elif side_effect:
237 super(StorageMethodMock, self).__init__(
238 name=name,
239 side_effect=_build_mock_object(side_effect))
240 elif return_value is not None:
241 super(StorageMethodMock, self).__init__(
242 name=name,
243 return_value=_build_mock_object(return_value))
244 else:
245 super(StorageMethodMock, self).__init__(
246 name=name, return_value=None)
249class StorageResourceMock(dict):
250 def __init__(self, yaml_file):
251 yaml_dict = utils.load_yaml(yaml_file)
252 if isinstance(yaml_dict, dict): 252 ↛ exitline 252 didn't return from function '__init__' because the condition on line 252 was always true
253 for section, sec_body in yaml_dict.items():
254 self[section] = {}
255 if isinstance(sec_body, dict): 255 ↛ 253line 255 didn't jump to line 253 because the condition on line 255 was always true
256 for obj_name, obj_body in sec_body.items():
257 self[section][obj_name] = _build_mock_object(obj_body)
260def _is_mock_object(yaml_info):
261 return (isinstance(yaml_info, dict) and
262 (SYMBOL_PROPERTIES in yaml_info or SYMBOL_METHODS in yaml_info))
265def _build_mock_object(yaml_dict):
266 if _is_mock_object(yaml_dict):
267 return StorageObjectMock(yaml_dict)
268 elif isinstance(yaml_dict, dict):
269 return {k: _build_mock_object(v) for k, v in yaml_dict.items()}
270 elif isinstance(yaml_dict, list):
271 return [_build_mock_object(each) for each in yaml_dict]
272 else:
273 return yaml_dict
276manila_res = ManilaResourceMock('mocked_manila.yaml')
277unity_res = StorageResourceMock('mocked_unity.yaml')
278STORAGE_RES_MAPPING = {
279 'TestClient': unity_res,
280 'TestConnection': unity_res,
281 'TestConnectionDHSSFalse': unity_res,
282}
285def mock_input(resource):
286 def inner_dec(func):
287 def decorated(cls, *args, **kwargs):
288 if cls._testMethodName in resource:
289 storage_res = resource[cls._testMethodName]
290 return func(cls, storage_res, *args, **kwargs)
292 return decorated
294 return inner_dec
297mock_client_input = mock_input(unity_res)
300def patch_client(func):
301 def client_decorator(cls, *args, **kwargs):
302 storage_res = {}
303 if func.__name__ in STORAGE_RES_MAPPING[cls.__class__.__name__]:
304 storage_res = (
305 STORAGE_RES_MAPPING[cls.__class__.__name__][func.__name__])
306 with utils.patch_system as patched_system:
307 if 'unity' in storage_res:
308 patched_system.return_value = storage_res['unity']
309 _client = client.UnityClient(host='fake_host',
310 username='fake_user',
311 password='fake_passwd')
312 return func(cls, _client, *args, **kwargs)
314 return client_decorator
317def mock_driver_input(resource):
318 def inner_dec(func):
319 def decorated(cls, *args, **kwargs):
320 return func(cls, resource, *args, **kwargs)
322 return decorated
324 return inner_dec
327mock_manila_input = mock_driver_input(manila_res)
330def patch_connection_init(func):
331 def connection_decorator(cls, *args, **kwargs):
332 storage_res = {}
333 if func.__name__ in STORAGE_RES_MAPPING[cls.__class__.__name__]:
334 storage_res = (
335 STORAGE_RES_MAPPING[cls.__class__.__name__][func.__name__])
336 with utils.patch_system as patched_system:
337 if 'unity' in storage_res:
338 patched_system.return_value = storage_res['unity']
339 conn = connection.UnityStorageConnection(LOG)
340 return func(cls, conn, *args, **kwargs)
342 return connection_decorator
345def do_connection_connect(conn, res):
346 conn.config = None
347 conn.client = client.UnityClient(host='fake_host',
348 username='fake_user',
349 password='fake_passwd')
350 conn.pool_conf = ['pool_1', 'pool_2']
351 conn.pool_set = set(['pool_1', 'pool_2'])
352 conn.reserved_percentage = 0
353 conn.reserved_snapshot_percentage = 0
354 conn.reserved_share_extend_percentage = 0
355 conn.max_over_subscription_ratio = 20
356 conn.port_set = set(['spa_eth1', 'spa_eth2'])
357 conn.nas_server_pool = StorageObjectMock(res['nas_server_pool'])
358 conn.storage_processor = StorageObjectMock(res['sp_a'])
359 conn.report_default_filter_function = False
362def patch_connection(func):
363 def connection_decorator(cls, *args, **kwargs):
364 storage_res = {}
365 if func.__name__ in STORAGE_RES_MAPPING[cls.__class__.__name__]:
366 storage_res = (
367 STORAGE_RES_MAPPING[cls.__class__.__name__][func.__name__])
368 with utils.patch_system as patched_system:
369 conn = connection.UnityStorageConnection(LOG)
370 if 'unity' in storage_res:
371 patched_system.return_value = storage_res['unity']
372 do_connection_connect(
373 conn, STORAGE_RES_MAPPING[cls.__class__.__name__])
374 return func(cls, conn, *args, **kwargs)
376 return connection_decorator