Coverage for manila/tests/share/drivers/huawei/test_huawei_nas.py: 96%
2025 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) 2014 Huawei Technologies Co., Ltd.
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.
16"""Unit tests for the Huawei nas driver module."""
19import os
20import requests
21import shutil
22import tempfile
23import time
24from unittest import mock
25import xml.dom.minidom
27import ddt
28from defusedxml import ElementTree as ET
29from oslo_serialization import jsonutils
31from manila.common import constants as common_constants
32from manila import context
33from manila.data import utils as data_utils
34from manila import db
35from manila import exception
36from manila import rpc
37from manila.share import configuration as conf
38from manila.share.drivers.huawei import constants
39from manila.share.drivers.huawei import huawei_nas
40from manila.share.drivers.huawei.v3 import connection
41from manila.share.drivers.huawei.v3 import helper
42from manila.share.drivers.huawei.v3 import replication
43from manila.share.drivers.huawei.v3 import rpcapi
44from manila.share.drivers.huawei.v3 import smartx
45from manila import test
46from manila import utils
49def fake_sleep(time):
50 pass
53def data_session(url):
54 if url == "/xx/sessions": 54 ↛ 59line 54 didn't jump to line 59 because the condition on line 54 was always true
55 data = """{"error":{"code":0},
56 "data":{"username":"admin",
57 "iBaseToken":"2001031430",
58 "deviceid":"210235G7J20000000000"}}"""
59 if url == "sessions": 59 ↛ 60line 59 didn't jump to line 60 because the condition on line 59 was never true
60 data = '{"error":{"code":0},"data":{"ID":11}}'
61 return data
64def filesystem(method, data, fs_status_flag):
65 extend_share_flag = False
66 shrink_share_flag = False
68 if method == "PUT":
69 if data == """{"CAPACITY": 10485760}""":
70 data = """{"error":{"code":0},
71 "data":{"ID":"4",
72 "CAPACITY":"8388608"}}"""
73 extend_share_flag = True
74 elif data == """{"CAPACITY": 2097152}""":
75 data = """{"error":{"code":0},
76 "data":{"ID":"4",
77 "CAPACITY":"2097152"}}"""
78 shrink_share_flag = True
79 elif data == """{"NAME": "share_fake_manage_uuid"}""":
80 data = """{"error":{"code":0},
81 "data":{"ID":"4",
82 "CAPACITY":"8388608"}}"""
83 elif data == jsonutils.dumps({"ENABLEDEDUP": True,
84 "ENABLECOMPRESSION": True}):
85 data = """{"error":{"code":0},
86 "data":{"ID":"4",
87 "CAPACITY":"8388608"}}"""
88 elif data == jsonutils.dumps({"ENABLEDEDUP": False,
89 "ENABLECOMPRESSION": False}):
90 data = """{"error":{"code":0},
91 "data":{"ID":"4",
92 "CAPACITY":"8388608"}}"""
93 elif data == """{"IOPRIORITY": "3"}""": 93 ↛ 124line 93 didn't jump to line 124 because the condition on line 93 was always true
94 data = """{"error":{"code":0}}"""
95 elif method == "DELETE":
96 data = """{"error":{"code":0}}"""
97 elif method == "GET": 97 ↛ 123line 97 didn't jump to line 123 because the condition on line 97 was always true
98 if fs_status_flag:
99 data = """{"error":{"code":0},
100 "data":{"HEALTHSTATUS":"1",
101 "RUNNINGSTATUS":"27",
102 "ALLOCTYPE":"1",
103 "CAPACITY":"8388608",
104 "PARENTNAME":"OpenStack_Pool",
105 "ENABLECOMPRESSION":"false",
106 "ENABLEDEDUP":"false",
107 "CACHEPARTITIONID":"",
108 "SMARTCACHEPARTITIONID":"",
109 "IOCLASSID":"11"}}"""
110 else:
111 data = """{"error":{"code":0},
112 "data":{"HEALTHSTATUS":"0",
113 "RUNNINGSTATUS":"27",
114 "ALLOCTYPE":"0",
115 "CAPACITY":"8388608",
116 "PARENTNAME":"OpenStack_Pool",
117 "ENABLECOMPRESSION":"false",
118 "ENABLEDEDUP":"false",
119 "CACHEPARTITIONID":"",
120 "SMARTCACHEPARTITIONID":"",
121 "IOCLASSID":"11"}}"""
122 else:
123 data = '{"error":{"code":31755596}}'
124 return (data, extend_share_flag, shrink_share_flag)
127def filesystem_thick(method, data, fs_status_flag):
128 extend_share_flag = False
129 shrink_share_flag = False
131 if method == "PUT":
132 if data == """{"CAPACITY": 10485760}""": 132 ↛ 133line 132 didn't jump to line 133 because the condition on line 132 was never true
133 data = """{"error":{"code":0},
134 "data":{"ID":"5",
135 "CAPACITY":"8388608"}}"""
136 extend_share_flag = True
137 elif data == """{"CAPACITY": 2097152}""": 137 ↛ 138line 137 didn't jump to line 138 because the condition on line 137 was never true
138 data = """{"error":{"code":0},
139 "data":{"ID":"5",
140 "CAPACITY":"2097152"}}"""
141 shrink_share_flag = True
142 elif data == """{"NAME": "share_fake_uuid_thickfs"}""": 142 ↛ 146line 142 didn't jump to line 146 because the condition on line 142 was always true
143 data = """{"error":{"code":0},
144 "data":{"ID":"5",
145 "CAPACITY":"8388608"}}"""
146 elif data == jsonutils.dumps({"ENABLEDEDUP": False,
147 "ENABLECOMPRESSION": False}):
148 data = """{"error":{"code":0},
149 "data":{"ID":"5",
150 "CAPACITY":"8388608"}}"""
151 elif method == "DELETE": 151 ↛ 152line 151 didn't jump to line 152 because the condition on line 151 was never true
152 data = """{"error":{"code":0}}"""
153 elif method == "GET": 153 ↛ 179line 153 didn't jump to line 179 because the condition on line 153 was always true
154 if fs_status_flag:
155 data = """{"error":{"code":0},
156 "data":{"HEALTHSTATUS":"1",
157 "RUNNINGSTATUS":"27",
158 "ALLOCTYPE":"0",
159 "CAPACITY":"8388608",
160 "PARENTNAME":"OpenStack_Pool_Thick",
161 "ENABLECOMPRESSION":"false",
162 "ENABLEDEDUP":"false",
163 "CACHEPARTITIONID":"",
164 "SMARTCACHEPARTITIONID":"",
165 "IOCLASSID":"11"}}"""
166 else:
167 data = """{"error":{"code":0},
168 "data":{"HEALTHSTATUS":"0",
169 "RUNNINGSTATUS":"27",
170 "ALLOCTYPE":"0",
171 "CAPACITY":"8388608",
172 "PARENTNAME":"OpenStack_Pool_Thick",
173 "ENABLECOMPRESSION":"false",
174 "ENABLEDEDUP":"false",
175 "CACHEPARTITIONID":"",
176 "SMARTCACHEPARTITIONID":"",
177 "IOCLASSID":"11"}}"""
178 else:
179 data = '{"error":{"code":31755596}}'
180 return (data, extend_share_flag, shrink_share_flag)
183def filesystem_inpartition(method, data, fs_status_flag):
184 extend_share_flag = False
185 shrink_share_flag = False
187 if method == "PUT":
188 if data == """{"CAPACITY": 10485760}""": 188 ↛ 189line 188 didn't jump to line 189 because the condition on line 188 was never true
189 data = """{"error":{"code":0},
190 "data":{"ID":"6",
191 "CAPACITY":"8388608"}}"""
192 extend_share_flag = True
193 elif data == """{"CAPACITY": 2097152}""": 193 ↛ 194line 193 didn't jump to line 194 because the condition on line 193 was never true
194 data = """{"error":{"code":0},
195 "data":{"ID":"6",
196 "CAPACITY":"2097152"}}"""
197 shrink_share_flag = True
198 elif data == """{"NAME": "share_fake_manage_uuid"}""": 198 ↛ 199line 198 didn't jump to line 199 because the condition on line 198 was never true
199 data = """{"error":{"code":0},
200 "data":{"ID":"6",
201 "CAPACITY":"8388608"}}"""
202 elif data == """{"NAME": "share_fake_uuid_inpartition"}""":
203 data = """{"error":{"code":0},
204 "data":{"ID":"6",
205 "CAPACITY":"8388608"}}"""
206 elif data == jsonutils.dumps({"ENABLEDEDUP": True, 206 ↛ 211line 206 didn't jump to line 211 because the condition on line 206 was always true
207 "ENABLECOMPRESSION": True}):
208 data = """{"error":{"code":0},
209 "data":{"ID":"6",
210 "CAPACITY":"8388608"}}"""
211 elif data == jsonutils.dumps({"ENABLEDEDUP": False,
212 "ENABLECOMPRESSION": False}):
213 data = """{"error":{"code":0},
214 "data":{"ID":"6",
215 "CAPACITY":"8388608"}}"""
216 elif method == "DELETE": 216 ↛ 217line 216 didn't jump to line 217 because the condition on line 216 was never true
217 data = """{"error":{"code":0}}"""
218 elif method == "GET": 218 ↛ 244line 218 didn't jump to line 244 because the condition on line 218 was always true
219 if fs_status_flag: 219 ↛ 232line 219 didn't jump to line 232 because the condition on line 219 was always true
220 data = """{"error":{"code":0},
221 "data":{"HEALTHSTATUS":"1",
222 "RUNNINGSTATUS":"27",
223 "ALLOCTYPE":"1",
224 "CAPACITY":"8388608",
225 "PARENTNAME":"OpenStack_Pool",
226 "ENABLECOMPRESSION":"false",
227 "ENABLEDEDUP":"false",
228 "CACHEPARTITIONID":"1",
229 "SMARTCACHEPARTITIONID":"1",
230 "IOCLASSID":"11"}}"""
231 else:
232 data = """{"error":{"code":0},
233 "data":{"HEALTHSTATUS":"0",
234 "RUNNINGSTATUS":"27",
235 "ALLOCTYPE":"0",
236 "CAPACITY":"8388608",
237 "PARENTNAME":"OpenStack_Pool",
238 "ENABLECOMPRESSION":"false",
239 "ENABLEDEDUP":"false",
240 "CACHEPARTITIONID":"1",
241 "SMARTCACHEPARTITIONID":"1",
242 "IOCLASSID":"11"}}"""
243 else:
244 data = '{"error":{"code":31755596}}'
245 return (data, extend_share_flag, shrink_share_flag)
248def allow_access(type, method, data):
249 allow_ro_flag = False
250 allow_rw_flag = False
251 request_data = jsonutils.loads(data)
252 success_data = """{"error":{"code":0}}"""
253 fail_data = """{"error":{"code":1077939723}}"""
254 ret = None
256 if type == "NFS":
257 if request_data['ACCESSVAL'] == '0':
258 allow_ro_flag = True
259 ret = success_data
260 elif request_data['ACCESSVAL'] == '1': 260 ↛ 271line 260 didn't jump to line 271 because the condition on line 260 was always true
261 allow_rw_flag = True
262 ret = success_data
263 elif type == "CIFS": 263 ↛ 271line 263 didn't jump to line 271 because the condition on line 263 was always true
264 if request_data['PERMISSION'] == '0':
265 allow_ro_flag = True
266 ret = success_data
267 elif request_data['PERMISSION'] == '1': 267 ↛ 271line 267 didn't jump to line 271 because the condition on line 267 was always true
268 allow_rw_flag = True
269 ret = success_data
270 # Group name should start with '@'.
271 if ('group' in request_data['NAME']
272 and not request_data['NAME'].startswith('@')):
273 ret = fail_data
275 if ret is None: 275 ↛ 276line 275 didn't jump to line 276 because the condition on line 275 was never true
276 ret = fail_data
277 return (ret, allow_ro_flag, allow_rw_flag)
280def dec_driver_handles_share_servers(func):
281 def wrapper(*args, **kw):
282 self = args[0]
283 self.configuration.driver_handles_share_servers = True
284 self.recreate_fake_conf_file(logical_port='CTE0.A.H0')
285 self.driver.plugin.configuration.manila_huawei_conf_file = (
286 self.fake_conf_file)
287 self.driver.plugin.helper.login()
288 return func(*args, **kw)
289 return wrapper
292def QoS_response(method):
293 if method == "GET":
294 data = """{"error":{"code":0},
295 "data":{"NAME": "OpenStack_Fake_QoS", "MAXIOPS": "100",
296 "FSLIST": "4", "LUNLIST": "", "RUNNINGSTATUS": "2"}}"""
297 elif method == "PUT":
298 data = """{"error":{"code":0}}"""
299 else:
300 data = """{"error":{"code":0},
301 "data":{"ID": "11"}}"""
302 return data
305class FakeHuaweiNasHelper(helper.RestHelper):
307 def __init__(self, *args, **kwargs):
308 helper.RestHelper.__init__(self, *args, **kwargs)
309 self.test_normal = True
310 self.deviceid = None
311 self.delete_flag = False
312 self.allow_flag = False
313 self.deny_flag = False
314 self.create_snapflag = False
315 self.setupserver_flag = False
316 self.fs_status_flag = True
317 self.create_share_flag = False
318 self.snapshot_flag = True
319 self.service_status_flag = True
320 self.share_exist = True
321 self.service_nfs_status_flag = True
322 self.create_share_data_flag = False
323 self.allow_ro_flag = False
324 self.allow_rw_flag = False
325 self.extend_share_flag = False
326 self.shrink_share_flag = False
327 self.add_fs_to_partition_flag = False
328 self.add_fs_to_cache_flag = False
329 self.test_multi_url_flag = 0
330 self.cache_exist = True
331 self.partition_exist = True
332 self.alloc_type = None
333 self.custom_results = {}
335 def _change_file_mode(self, filepath):
336 pass
338 def do_call(self, url, data, method, calltimeout=4):
339 url = url.replace('http://100.115.10.69:8082/deviceManager/rest', '')
340 url = url.replace('/210235G7J20000000000/', '')
342 if self.custom_results and self.custom_results.get(url):
343 result = self.custom_results[url]
344 if isinstance(result, str):
345 return jsonutils.loads(result)
347 if isinstance(result, dict) and result.get(method): 347 ↛ 350line 347 didn't jump to line 350 because the condition on line 347 was always true
348 return jsonutils.loads(result[method])
350 if self.test_normal:
351 if self.test_multi_url_flag == 1:
352 data = '{"error":{"code":-403}}'
353 res_json = jsonutils.loads(data)
354 return res_json
355 elif self.test_multi_url_flag == 2:
356 if ('http://100.115.10.70:8082/deviceManager/rest/xx/' 356 ↛ 358line 356 didn't jump to line 358 because the condition on line 356 was never true
357 'sessions' == url):
358 self.url = url
359 data = data_session("/xx/sessions")
360 res_json = jsonutils.loads(data)
361 return res_json
362 elif (('/xx/sessions' == url) or (self.url is not None 362 ↛ 365line 362 didn't jump to line 365 because the condition on line 362 was never true
363 and 'http://100.115.10.69:8082/deviceManager/rest'
364 in self.url)):
365 data = '{"error":{"code":-403}}'
366 res_json = jsonutils.loads(data)
367 return res_json
369 if url == "/xx/sessions" or url == "/sessions":
370 data = data_session(url)
372 if url == "/storagepool":
373 data = """{"error":{"code":0},
374 "data":[{"USERFREECAPACITY":"2097152",
375 "ID":"1",
376 "NAME":"OpenStack_Pool",
377 "USERTOTALCAPACITY":"4194304",
378 "USAGETYPE":"2",
379 "USERCONSUMEDCAPACITY":"2097152",
380 "TIER0CAPACITY":"100",
381 "TIER1CAPACITY":"0",
382 "TIER2CAPACITY":"0"},
383 {"USERFREECAPACITY":"2097152",
384 "ID":"2",
385 "NAME":"OpenStack_Pool_Thick",
386 "USERTOTALCAPACITY":"4194304",
387 "USAGETYPE":"2",
388 "USERCONSUMEDCAPACITY":"2097152",
389 "TIER0CAPACITY":"100",
390 "TIER1CAPACITY":"0",
391 "TIER2CAPACITY":"0"}]}"""
393 if url == "/filesystem":
394 request_data = jsonutils.loads(data)
395 self.alloc_type = request_data.get('ALLOCTYPE')
396 data = """{"error":{"code":0},"data":{
397 "ID":"4"}}"""
399 if url == "/system/":
400 data = """{"error":{"code":0},
401 "data":{"PRODUCTVERSION": "V300R003C10",
402 "wwn": "fake_wwn"}}"""
404 if url == "/remote_device":
405 data = """{"error":{"code":0},
406 "data":[{"ID": "0",
407 "NAME": "fake_name",
408 "WWN": "fake_wwn"}]}"""
410 if url == "/ioclass" or url == "/ioclass/11":
411 data = QoS_response(method)
413 if url == "/ioclass/active/11":
414 data = """{"error":{"code":0},
415 "data":[{"ID": "11", "MAXIOPS": "100",
416 "FSLIST": ""}]}"""
418 if url == "/NFSHARE" or url == "/CIFSHARE":
419 if self.create_share_flag: 419 ↛ 420line 419 didn't jump to line 420 because the condition on line 419 was never true
420 data = '{"error":{"code":31755596}}'
421 elif self.create_share_data_flag: 421 ↛ 422line 421 didn't jump to line 422 because the condition on line 421 was never true
422 data = '{"error":{"code":0}}'
423 else:
424 data = """{"error":{"code":0},"data":{
425 "ID":"10"}}"""
427 if url == "/NFSHARE?range=[100-200]":
428 if self.share_exist:
429 data = """{"error":{"code":0},
430 "data":[{"ID":"1",
431 "FSID":"4",
432 "NAME":"test",
433 "SHAREPATH":"/share_fake_uuid/"},
434 {"ID":"2",
435 "FSID":"5",
436 "NAME":"test",
437 "SHAREPATH":"/share_fake_uuid_thickfs/"},
438 {"ID":"3",
439 "FSID":"6",
440 "NAME":"test",
441 "SHAREPATH":"/share_fake_uuid_inpartition/"}]}"""
442 else:
443 data = """{"error":{"code":0},
444 "data":[{"ID":"1",
445 "FSID":"4",
446 "NAME":"test",
447 "SHAREPATH":"/share_fake_uuid_fail/"}]}"""
449 if url == "/CIFSHARE?range=[100-200]":
450 data = """{"error":{"code":0},
451 "data":[{"ID":"2",
452 "FSID":"4",
453 "NAME":"test",
454 "SHAREPATH":"/share_fake_uuid/"}]}"""
456 if url == "/NFSHARE?range=[0-100]":
457 data = """{"error":{"code":0},
458 "data":[{"ID":"1",
459 "FSID":"4",
460 "NAME":"test_fail",
461 "SHAREPATH":"/share_fake_uuid_fail/"}]}"""
463 if url == "/CIFSHARE?range=[0-100]":
464 data = """{"error":{"code":0},
465 "data":[{"ID":"2",
466 "FSID":"4",
467 "NAME":"test_fail",
468 "SHAREPATH":"/share_fake_uuid_fail/"}]}"""
470 if url == "/NFSHARE/1" or url == "/CIFSHARE/2":
471 data = """{"error":{"code":0}}"""
472 self.delete_flag = True
474 if url == "/FSSNAPSHOT":
475 data = """{"error":{"code":0},"data":{
476 "ID":"3"}}"""
477 self.create_snapflag = True
479 if url == "/FSSNAPSHOT/4@share_snapshot_fake_snapshot_uuid":
480 if self.snapshot_flag:
481 data = """{"error":{"code":0},
482 "data":{"ID":"4@share_snapshot_fake_snapshot_uuid"}}"""
483 else:
484 data = '{"error":{"code":1073754118}}'
485 self.delete_flag = True
487 if url == "/FSSNAPSHOT/4@fake_storage_snapshot_name":
488 if self.snapshot_flag: 488 ↛ 494line 488 didn't jump to line 494 because the condition on line 488 was always true
489 data = """{"error":{"code":0},
490 "data":{"ID":"4@share_snapshot_fake_snapshot_uuid",
491 "NAME":"share_snapshot_fake_snapshot_uuid",
492 "HEALTHSTATUS":"1"}}"""
493 else:
494 data = '{"error":{"code":1073754118}}'
496 if url == "/FSSNAPSHOT/3": 496 ↛ 497line 496 didn't jump to line 497 because the condition on line 496 was never true
497 data = """{"error":{"code":0}}"""
498 self.delete_flag = True
500 if url == "/NFS_SHARE_AUTH_CLIENT":
501 data, self.allow_ro_flag, self.allow_rw_flag = (
502 allow_access('NFS', method, data))
503 self.allow_flag = True
505 if url == "/CIFS_SHARE_AUTH_CLIENT":
506 data, self.allow_ro_flag, self.allow_rw_flag = (
507 allow_access('CIFS', method, data))
508 self.allow_flag = True
510 if url == ("/FSSNAPSHOT?TYPE=48&PARENTID=4" 510 ↛ 512line 510 didn't jump to line 512 because the condition on line 510 was never true
511 "&&sortby=TIMESTAMP,d&range=[0-2000]"):
512 data = """{"error":{"code":0},
513 "data":[{"ID":"3",
514 "NAME":"share_snapshot_fake_snapshot_uuid"}]}"""
515 self.delete_flag = True
517 if url == ("/NFS_SHARE_AUTH_CLIENT?"
518 "filter=PARENTID::1&range=[0-100]"):
519 data = """{"error":{"code":0},
520 "data":[{"ID":"0",
521 "NAME":"100.112.0.1_fail"}]}"""
523 if url == ("/CIFS_SHARE_AUTH_CLIENT?"
524 "filter=PARENTID::2&range=[0-100]"):
525 data = """{"error":{"code":0},
526 "data":[{"ID":"0",
527 "NAME":"user_name_fail"}]}"""
529 if url == ("/NFS_SHARE_AUTH_CLIENT?"
530 "filter=PARENTID::1&range=[100-200]"):
531 data = """{"error":{"code":0},
532 "data":[{"ID":"5",
533 "NAME":"100.112.0.2"}]}"""
535 if url == ("/CIFS_SHARE_AUTH_CLIENT?"
536 "filter=PARENTID::2&range=[100-200]"):
537 data = """{"error":{"code":0},
538 "data":[{"ID":"6",
539 "NAME":"user_exist"}]}"""
541 if url in ("/NFS_SHARE_AUTH_CLIENT/0",
542 "/NFS_SHARE_AUTH_CLIENT/5",
543 "/CIFS_SHARE_AUTH_CLIENT/0",
544 "/CIFS_SHARE_AUTH_CLIENT/6"):
545 if method == "DELETE":
546 data = """{"error":{"code":0}}"""
547 self.deny_flag = True
548 elif method == "GET":
549 if 'CIFS' in url:
550 data = """{"error":{"code":0},
551 "data":{"'PERMISSION'":"0"}}"""
552 else:
553 data = """{"error":{"code":0},
554 "data":{"ACCESSVAL":"0"}}"""
555 else:
556 data = """{"error":{"code":0}}"""
557 self.allow_rw_flagg = True
559 if url == "/NFSHARE/count" or url == "/CIFSHARE/count":
560 data = """{"error":{"code":0},"data":{
561 "COUNT":"196"}}"""
563 if (url == "/NFS_SHARE_AUTH_CLIENT/count?filter=PARENTID::1"
564 or url == ("/CIFS_SHARE_AUTH_CLIENT/count?filter="
565 "PARENTID::2")):
566 data = """{"error":{"code":0},"data":{
567 "COUNT":"196"}}"""
569 if url == "/CIFSSERVICE":
570 if self.service_status_flag:
571 data = """{"error":{"code":0},"data":{
572 "RUNNINGSTATUS":"2"}}"""
573 else:
574 data = """{"error":{"code":0},"data":{
575 "RUNNINGSTATUS":"1"}}"""
577 if url == "/NFSSERVICE":
578 if self.service_nfs_status_flag:
579 data = """{"error":{"code":0},
580 "data":{"RUNNINGSTATUS":"2",
581 "SUPPORTV3":"true",
582 "SUPPORTV4":"true"}}"""
583 else:
584 data = """{"error":{"code":0},
585 "data":{"RUNNINGSTATUS":"1",
586 "SUPPORTV3":"true",
587 "SUPPORTV4":"true"}}"""
588 self.setupserver_flag = True
590 if "/FILESYSTEM?filter=NAME::" in url:
591 data = """{"error":{"code":0},
592 "data":[{"ID":"4",
593 "NAME":"share_fake_uuid"},
594 {"ID":"8",
595 "NAME":"share_fake_new_uuid"}]}"""
597 if url == "/filesystem/4":
598 data, self.extend_share_flag, self.shrink_share_flag = (
599 filesystem(method, data, self.fs_status_flag))
600 self.delete_flag = True
602 if url == "/filesystem/5":
603 data, self.extend_share_flag, self.shrink_share_flag = (
604 filesystem_thick(method, data, self.fs_status_flag))
605 self.delete_flag = True
607 if url == "/filesystem/6":
608 data, self.extend_share_flag, self.shrink_share_flag = (
609 filesystem_inpartition(method, data, self.fs_status_flag))
610 self.delete_flag = True
612 if url == "/cachepartition":
613 if self.partition_exist:
614 data = """{"error":{"code":0},
615 "data":[{"ID":"7",
616 "NAME":"test_partition_name"}]}"""
617 else:
618 data = """{"error":{"code":0},
619 "data":[{"ID":"7",
620 "NAME":"test_partition_name_fail"}]}"""
622 if url == "/cachepartition/1":
623 if self.partition_exist: 623 ↛ 628line 623 didn't jump to line 628 because the condition on line 623 was always true
624 data = """{"error":{"code":0},
625 "data":{"ID":"7",
626 "NAME":"test_partition_name"}}"""
627 else:
628 data = """{"error":{"code":0},
629 "data":{"ID":"7",
630 "NAME":"test_partition_name_fail"}}"""
632 if url == "/SMARTCACHEPARTITION":
633 if self.cache_exist:
634 data = """{"error":{"code":0},
635 "data":[{"ID":"8",
636 "NAME":"test_cache_name"}]}"""
637 else:
638 data = """{"error":{"code":0},
639 "data":[{"ID":"8",
640 "NAME":"test_cache_name_fail"}]}"""
642 if url == "/SMARTCACHEPARTITION/1":
643 if self.cache_exist: 643 ↛ 648line 643 didn't jump to line 648 because the condition on line 643 was always true
644 data = """{"error":{"code":0},
645 "data":{"ID":"8",
646 "NAME":"test_cache_name"}}"""
647 else:
648 data = """{"error":{"code":0},
649 "data":{"ID":"8",
650 "NAME":"test_cache_name_fail"}}"""
652 if url == "/filesystem/associate/cachepartition":
653 data = """{"error":{"code":0}}"""
654 self.add_fs_to_partition_flag = True
656 if url == "/SMARTCACHEPARTITION/CREATE_ASSOCIATE":
657 data = """{"error":{"code":0}}"""
658 self.add_fs_to_cache_flag = True
660 if url == "/SMARTCACHEPARTITION/REMOVE_ASSOCIATE":
661 data = """{"error":{"code":0}}"""
663 if url == "/smartPartition/removeFs":
664 data = """{"error":{"code":0}}"""
666 if url == "/ETH_PORT":
667 data = """{"error":{"code":0},
668 "data":[{"ID": "4",
669 "LOCATION":"CTE0.A.H0",
670 "IPV4ADDR":"",
671 "BONDNAME":"",
672 "BONDID":"",
673 "RUNNINGSTATUS":"10"},
674 {"ID": "6",
675 "LOCATION":"CTE0.A.H1",
676 "IPV4ADDR":"",
677 "BONDNAME":"fake_bond",
678 "BONDID":"5",
679 "RUNNINGSTATUS":"10"}]}"""
681 if url == "/ETH_PORT/6":
682 data = """{"error":{"code":0},
683 "data":{"ID": "6",
684 "LOCATION":"CTE0.A.H1",
685 "IPV4ADDR":"",
686 "BONDNAME":"fake_bond",
687 "BONDID":"5",
688 "RUNNINGSTATUS":"10"}}"""
690 if url == "/BOND_PORT":
691 data = "{\"error\":{\"code\":0},\
692 \"data\":[{\"ID\": \"5\",\
693 \"NAME\":\"fake_bond\",\
694 \"PORTIDLIST\": \"[\\\"6\\\"]\",\
695 \"RUNNINGSTATUS\":\"10\"}]}"
697 if url == "/vlan":
698 if method == "GET":
699 data = """{"error":{"code":0}}"""
700 else:
701 data = """{"error":{"code":0},"data":{
702 "ID":"4"}}"""
704 if url == "/LIF":
705 if method == "GET":
706 data = """{"error":{"code":0}}"""
707 else:
708 data = """{"error":{"code":0},"data":{
709 "ID":"4"}}"""
711 if url == "/DNS_Server":
712 if method == "GET":
713 data = "{\"error\":{\"code\":0},\"data\":{\
714 \"ADDRESS\":\"[\\\"\\\"]\"}}"
715 else:
716 data = """{"error":{"code":0}}"""
718 if url == "/AD_CONFIG":
719 if method == "GET": 719 ↛ 720line 719 didn't jump to line 720 because the condition on line 719 was never true
720 data = """{"error":{"code":0},"data":{
721 "DOMAINSTATUS":"1",
722 "FULLDOMAINNAME":"huawei.com"}}"""
723 else:
724 data = """{"error":{"code":0}}"""
726 if url == "/LDAP_CONFIG":
727 if method == "GET": 727 ↛ 728line 727 didn't jump to line 728 because the condition on line 727 was never true
728 data = """{"error":{"code":0},"data":{
729 "BASEDN":"dc=huawei,dc=com",
730 "LDAPSERVER": "100.97.5.87"}}"""
731 else:
732 data = """{"error":{"code":0}}"""
734 if url == "/REPLICATIONPAIR":
735 data = """{"error":{"code":0},"data":{
736 "ID":"fake_pair_id"}}"""
738 if url == "/REPLICATIONPAIR/sync":
739 data = """{"error":{"code":0}}"""
741 if url == "/REPLICATIONPAIR/switch":
742 data = """{"error":{"code":0}}"""
744 if url == "/REPLICATIONPAIR/split":
745 data = """{"error":{"code":0}}"""
747 if url == "/REPLICATIONPAIR/CANCEL_SECODARY_WRITE_LOCK":
748 data = """{"error":{"code":0}}"""
750 if url == "/REPLICATIONPAIR/SET_SECODARY_WRITE_LOCK":
751 data = """{"error":{"code":0}}"""
753 if url == "/REPLICATIONPAIR/fake_pair_id":
754 data = """{"error":{"code":0},"data":{
755 "ID": "fake_pair_id",
756 "HEALTHSTATUS": "1",
757 "SECRESDATASTATUS": "1",
758 "ISPRIMARY": "false",
759 "SECRESACCESS": "1",
760 "RUNNINGSTATUS": "1"}}"""
761 else:
762 data = '{"error":{"code":31755596}}'
764 res_json = jsonutils.loads(data)
765 return res_json
768class FakeRpcClient(rpcapi.HuaweiV3API):
769 def __init__(self, helper):
770 super(FakeRpcClient, self).__init__()
771 self.replica_mgr = replication.ReplicaPairManager(helper)
773 class fake_call_context(object):
774 def __init__(self, replica_mgr):
775 self.replica_mgr = replica_mgr
777 def call(self, context, func_name, **kwargs):
778 if func_name == 'create_replica_pair': 778 ↛ exitline 778 didn't return from function 'call' because the condition on line 778 was always true
779 return self.replica_mgr.create_replica_pair(
780 context, **kwargs)
782 def create_replica_pair(self, context, host, local_share_info,
783 remote_device_wwn, remote_fs_id):
784 self.client.prepare = mock.Mock(
785 return_value=self.fake_call_context(self.replica_mgr))
786 return super(FakeRpcClient, self).create_replica_pair(
787 context, host, local_share_info,
788 remote_device_wwn, remote_fs_id)
791class FakeRpcServer(object):
792 def start(self):
793 pass
796class FakePrivateStorage(object):
797 def __init__(self):
798 self.map = {}
800 def get(self, entity_id, key=None, default=None):
801 if self.map.get(entity_id):
802 return self.map[entity_id].get(key, default)
804 return default
806 def update(self, entity_id, details, delete_existing=False):
807 self.map[entity_id] = details
809 def delete(self, entity_id, key=None):
810 self.map.pop(entity_id)
813class FakeHuaweiNasDriver(huawei_nas.HuaweiNasDriver):
814 """Fake HuaweiNasDriver."""
816 def __init__(self, *args, **kwargs):
817 huawei_nas.HuaweiNasDriver.__init__(self, *args, **kwargs)
818 self.plugin = connection.V3StorageConnection(self.configuration)
820 self.plugin.helper = FakeHuaweiNasHelper(self.configuration)
821 self.plugin.replica_mgr = replication.ReplicaPairManager(
822 self.plugin.helper)
823 self.plugin.rpc_client = FakeRpcClient(self.plugin.helper)
824 self.plugin.private_storage = FakePrivateStorage()
827class FakeConfigParseTree(object):
828 class FakeNode(object):
829 def __init__(self, text):
830 self._text = text
832 @property
833 def text(self):
834 return self._text
836 @text.setter
837 def text(self, text):
838 self._text = text
840 class FakeRoot(object):
841 def __init__(self):
842 self._node_map = {}
844 def findtext(self, path, default=None):
845 if path in self._node_map: 845 ↛ 847line 845 didn't jump to line 847 because the condition on line 845 was always true
846 return self._node_map[path].text
847 return default
849 def find(self, path):
850 if path in self._node_map: 850 ↛ 852line 850 didn't jump to line 852 because the condition on line 850 was always true
851 return self._node_map[path]
852 return None
854 def __init__(self, path_value):
855 self.root = self.FakeRoot()
856 for k in path_value:
857 self.root._node_map[k] = self.FakeNode(path_value[k])
859 def getroot(self):
860 return self.root
862 def write(self, filename, format):
863 pass
866@ddt.ddt
867class HuaweiShareDriverTestCase(test.TestCase):
868 """Tests GenericShareDriver."""
870 def setUp(self):
871 super(HuaweiShareDriverTestCase, self).setUp()
872 self._context = context.get_admin_context()
874 def _safe_get(opt):
875 return getattr(self.configuration, opt)
877 self.configuration = mock.Mock(spec=conf.Configuration)
878 self.configuration.safe_get = mock.Mock(side_effect=_safe_get)
879 self.configuration.network_config_group = 'fake_network_config_group'
880 self.configuration.admin_network_config_group = (
881 'fake_admin_network_config_group')
882 self.configuration.config_group = 'fake_share_backend_name'
883 self.configuration.share_backend_name = 'fake_share_backend_name'
884 self.configuration.huawei_share_backend = 'V3'
885 self.configuration.max_over_subscription_ratio = 1
886 self.configuration.driver_handles_share_servers = False
887 self.configuration.replication_domain = None
888 self.configuration.filter_function = None
889 self.configuration.goodness_function = None
891 self.tmp_dir = tempfile.mkdtemp()
892 self.fake_conf_file = self.tmp_dir + '/manila_huawei_conf.xml'
893 self.addCleanup(shutil.rmtree, self.tmp_dir)
894 self.create_fake_conf_file(self.fake_conf_file)
895 self.addCleanup(os.remove, self.fake_conf_file)
897 self.configuration.manila_huawei_conf_file = self.fake_conf_file
898 self._helper_fake = mock.Mock()
899 self.mock_object(huawei_nas.importutils, 'import_object',
900 mock.Mock(return_value=self._helper_fake))
902 self.mock_object(time, 'sleep', fake_sleep)
903 self.driver = FakeHuaweiNasDriver(configuration=self.configuration)
904 self.driver.plugin.helper.test_normal = True
906 self.share_nfs = {
907 'id': 'fake_uuid',
908 'share_id': 'fake_uuid',
909 'project_id': 'fake_tenant_id',
910 'display_name': 'fake',
911 'name': 'share-fake-uuid',
912 'size': 1,
913 'share_proto': 'NFS',
914 'share_network_id': 'fake_net_id',
915 'share_server_id': 'fake-share-srv-id',
916 'export_locations': [
917 {'path': '100.115.10.68:/share_fake_uuid'},
918 ],
919 'host': 'fake_host@fake_backend#OpenStack_Pool',
920 'share_type_id': 'fake_id',
921 }
923 self.share_nfs_thick = {
924 'id': 'fake_uuid',
925 'project_id': 'fake_tenant_id',
926 'display_name': 'fake',
927 'name': 'share-fake-uuid',
928 'size': 1,
929 'share_proto': 'NFS',
930 'share_network_id': 'fake_net_id',
931 'share_server_id': 'fake-share-srv-id',
932 'host': 'fake_host@fake_backend#OpenStack_Pool_Thick',
933 'export_locations': [
934 {'path': '100.115.10.68:/share_fake_uuid'},
935 ],
936 'share_type_id': 'fake_id',
937 }
939 self.share_nfs_thickfs = {
940 'id': 'fake_uuid',
941 'project_id': 'fake_tenant_id',
942 'display_name': 'fake',
943 'name': 'share-fake-uuid-thickfs',
944 'size': 1,
945 'share_proto': 'NFS',
946 'share_network_id': 'fake_net_id',
947 'share_server_id': 'fake-share-srv-id',
948 'host': 'fake_host@fake_backend#OpenStack_Pool',
949 'export_locations': [
950 {'path': '100.115.10.68:/share_fake_uuid_thickfs'},
951 ],
952 'share_type_id': 'fake_id',
953 }
955 self.share_nfs_thick_thickfs = {
956 'id': 'fake_uuid',
957 'project_id': 'fake_tenant_id',
958 'display_name': 'fake',
959 'name': 'share-fake-uuid-thickfs',
960 'size': 1,
961 'share_proto': 'NFS',
962 'share_network_id': 'fake_net_id',
963 'share_server_id': 'fake-share-srv-id',
964 'host': 'fake_host@fake_backend#OpenStack_Pool_Thick',
965 'export_locations': [
966 {'path': '100.115.10.68:/share_fake_uuid_thickfs'},
967 ],
968 'share_type_id': 'fake_id',
969 }
971 self.share_nfs_inpartition = {
972 'id': 'fake_uuid',
973 'project_id': 'fake_tenant_id',
974 'display_name': 'fake',
975 'name': 'share-fake-uuid-inpartition',
976 'size': 1,
977 'share_proto': 'NFS',
978 'share_network_id': 'fake_net_id',
979 'share_server_id': 'fake-share-srv-id',
980 'host': 'fake_host@fake_backend#OpenStack_Pool',
981 'export_locations': [
982 {'path': '100.115.10.68:/share_fake_uuid_inpartition'},
983 ],
984 'share_type_id': 'fake_id',
985 }
987 self.share_manage_nfs = {
988 'id': 'fake_uuid',
989 'project_id': 'fake_tenant_id',
990 'display_name': 'fake',
991 'name': 'share-fake-manage-uuid',
992 'size': 1,
993 'share_proto': 'NFS',
994 'share_network_id': 'fake_net_id',
995 'share_server_id': 'fake-share-srv-id',
996 'export_locations': [
997 {'path': '100.115.10.68:/share_fake_uuid'},
998 ],
999 'host': 'fake_host@fake_backend#OpenStack_Pool',
1000 'share_type_id': 'fake_id',
1001 }
1003 self.share_pool_name_not_match = {
1004 'id': 'fake_uuid',
1005 'project_id': 'fake_tenant_id',
1006 'display_name': 'fake',
1007 'name': 'share-fake-manage-uuid',
1008 'size': 1,
1009 'share_proto': 'NFS',
1010 'share_network_id': 'fake_net_id',
1011 'share_server_id': 'fake-share-srv-id',
1012 'export_locations': [
1013 {'path': '100.115.10.68:/share_fake_uuid'},
1014 ],
1015 'host': 'fake_host@fake_backend#OpenStack_Pool_not_match',
1016 'share_type_id': 'fake_id',
1017 }
1019 self.share_proto_fail = {
1020 'id': 'fake_uuid',
1021 'project_id': 'fake_tenant_id',
1022 'display_name': 'fake',
1023 'name': 'share-fake-uuid',
1024 'size': 1,
1025 'share_proto': 'proto_fail',
1026 'share_network_id': 'fake_net_id',
1027 'share_server_id': 'fake-share-srv-id',
1028 'host': 'fake_host@fake_backend#OpenStack_Pool',
1029 }
1031 self.share_cifs = {
1032 'id': 'fake_uuid',
1033 'share_id': 'fake_uuid',
1034 'project_id': 'fake_tenant_id',
1035 'display_name': 'fake',
1036 'name': 'share-fake-uuid',
1037 'size': 1,
1038 'share_proto': 'CIFS',
1039 'share_network_id': 'fake_net_id',
1040 'share_server_id': 'fake-share-srv-id',
1041 'export_locations': [
1042 {'path': 'share_fake_uuid'},
1043 ],
1044 'host': 'fake_host@fake_backend#OpenStack_Pool',
1045 'share_type_id': 'fake_id',
1046 }
1048 self.share_manage_cifs = {
1049 'id': 'fake_uuid',
1050 'project_id': 'fake_tenant_id',
1051 'display_name': 'fake',
1052 'name': 'share-fake-manage-uuid',
1053 'size': 1,
1054 'share_proto': 'CIFS',
1055 'share_network_id': 'fake_net_id',
1056 'share_server_id': 'fake-share-srv-id',
1057 'export_locations': [
1058 {'path': '\\\\100.115.10.68\\share_fake_uuid'},
1059 ],
1060 'host': 'fake_host@fake_backend#OpenStack_Pool',
1061 'share_type_id': 'fake_id',
1062 }
1064 self.nfs_snapshot = {
1065 'id': 'fake_snapshot_uuid',
1066 'snapshot_id': 'fake_snapshot_uuid',
1067 'display_name': 'snapshot',
1068 'name': 'fake_snapshot_name',
1069 'size': 1,
1070 'share_name': 'share_fake_uuid',
1071 'share_id': 'fake_uuid',
1072 'share': {
1073 'share_name': 'share_fake_uuid',
1074 'share_id': 'fake_uuid',
1075 'share_size': 1,
1076 'share_proto': 'NFS',
1077 },
1078 }
1080 self.cifs_snapshot = {
1081 'id': 'fake_snapshot_uuid',
1082 'snapshot_id': 'fake_snapshot_uuid',
1083 'display_name': 'snapshot',
1084 'name': 'fake_snapshot_name',
1085 'size': 1,
1086 'share_name': 'share_fake_uuid',
1087 'share_id': 'fake_uuid',
1088 'share': {
1089 'share_name': 'share_fake_uuid',
1090 'share_id': 'fake_uuid',
1091 'share_size': 1,
1092 'share_proto': 'CIFS',
1093 },
1094 }
1096 self.storage_nfs_snapshot = {
1097 'id': 'fake_snapshot_uuid',
1098 'snapshot_id': 'fake_snapshot_uuid',
1099 'display_name': 'snapshot',
1100 'name': 'fake_snapshot_name',
1101 'provider_location': 'fake_storage_snapshot_name',
1102 'size': 1,
1103 'share_name': 'share_fake_uuid',
1104 'share_id': 'fake_uuid',
1105 'share': {
1106 'share_name': 'share_fake_uuid',
1107 'share_id': 'fake_uuid',
1108 'share_size': 1,
1109 'share_proto': 'NFS',
1110 },
1111 }
1113 self.storage_cifs_snapshot = {
1114 'id': 'fake_snapshot_uuid',
1115 'snapshot_id': 'fake_snapshot_uuid',
1116 'display_name': 'snapshot',
1117 'name': 'fake_snapshot_name',
1118 'provider_location': 'fake_storage_snapshot_name',
1119 'size': 1,
1120 'share_name': 'share_fake_uuid',
1121 'share_id': 'fake_uuid',
1122 'share': {
1123 'share_name': 'share_fake_uuid',
1124 'share_id': 'fake_uuid',
1125 'share_size': 1,
1126 'share_proto': 'CIFS',
1127 },
1128 }
1130 self.security_service = {
1131 'id': 'fake_id',
1132 'domain': 'FAKE',
1133 'server': 'fake_server',
1134 'user': 'fake_user',
1135 'password': 'fake_password',
1136 }
1138 self.access_ip = {
1139 'access_type': 'ip',
1140 'access_to': '100.112.0.1',
1141 'access_level': 'rw',
1142 }
1144 self.access_ip_exist = {
1145 'access_type': 'ip',
1146 'access_to': '100.112.0.2',
1147 'access_level': 'rw',
1148 }
1150 self.access_user = {
1151 'access_type': 'user',
1152 'access_to': 'user_name',
1153 'access_level': 'rw',
1154 }
1156 self.access_user_exist = {
1157 'access_type': 'user',
1158 'access_to': 'user_exist',
1159 'access_level': 'rw',
1160 }
1162 self.access_group = {
1163 'access_type': 'user',
1164 'access_to': 'group_name',
1165 'access_level': 'rw',
1166 }
1168 self.access_cert = {
1169 'access_type': 'cert',
1170 'access_to': 'fake_cert',
1171 'access_level': 'rw',
1172 }
1174 self.driver_options = {
1175 'volume_id': 'fake',
1176 }
1177 self.share_server = None
1178 self.driver._licenses = ['fake']
1180 self.fake_network_allocations = [{
1181 'id': 'fake_network_allocation_id',
1182 'ip_address': '111.111.111.109',
1183 }]
1184 self.fake_network_info = [{
1185 'server_id': '0',
1186 'segmentation_id': '2',
1187 'cidr': '111.111.111.0/24',
1188 'neutron_net_id': 'fake_neutron_net_id',
1189 'neutron_subnet_id': 'fake_neutron_subnet_id',
1190 'security_services': '',
1191 'network_allocations': self.fake_network_allocations,
1192 'network_type': 'vlan',
1193 }]
1194 self.fake_active_directory = {
1195 'type': 'active_directory',
1196 'dns_ip': '100.97.5.5',
1197 'user': 'ad_user',
1198 'password': 'ad_password',
1199 'domain': 'huawei.com'
1200 }
1201 self.fake_ldap = {
1202 'type': 'ldap',
1203 'server': '100.97.5.87',
1204 'domain': 'dc=huawei,dc=com'
1205 }
1207 fake_share_type_id_not_extra = 'fake_id'
1208 self.fake_type_not_extra = {
1209 'test_with_extra': {
1210 'created_at': 'fake_time',
1211 'deleted': '0',
1212 'deleted_at': None,
1213 'extra_specs': {},
1214 'required_extra_specs': {},
1215 'id': fake_share_type_id_not_extra,
1216 'name': 'test_with_extra',
1217 'updated_at': None
1218 }
1219 }
1221 fake_extra_specs = {
1222 'capabilities:dedupe': '<is> True',
1223 'capabilities:compression': '<is> True',
1224 'capabilities:huawei_smartcache': '<is> True',
1225 'huawei_smartcache:cachename': 'test_cache_name',
1226 'capabilities:huawei_smartpartition': '<is> True',
1227 'huawei_smartpartition:partitionname': 'test_partition_name',
1228 'capabilities:thin_provisioning': '<is> True',
1229 'test:test:test': 'test',
1230 }
1232 fake_share_type_id = 'fooid-2'
1233 self.fake_type_w_extra = {
1234 'test_with_extra': {
1235 'created_at': 'fake_time',
1236 'deleted': '0',
1237 'deleted_at': None,
1238 'extra_specs': fake_extra_specs,
1239 'required_extra_specs': {},
1240 'id': fake_share_type_id,
1241 'name': 'test_with_extra',
1242 'updated_at': None
1243 }
1244 }
1246 fake_extra_specs = {
1247 'capabilities:dedupe': '<is> True',
1248 'capabilities:compression': '<is> True',
1249 'capabilities:huawei_smartcache': '<is> False',
1250 'huawei_smartcache:cachename': None,
1251 'capabilities:huawei_smartpartition': '<is> False',
1252 'huawei_smartpartition:partitionname': None,
1253 'capabilities:thin_provisioning': '<is> True',
1254 'test:test:test': 'test',
1255 }
1257 fake_share_type_id = 'fooid-3'
1258 self.fake_type_fake_extra = {
1259 'test_with_extra': {
1260 'created_at': 'fake_time',
1261 'deleted': '0',
1262 'deleted_at': None,
1263 'extra_specs': fake_extra_specs,
1264 'required_extra_specs': {},
1265 'id': fake_share_type_id,
1266 'name': 'test_with_extra',
1267 'updated_at': None
1268 }
1269 }
1271 fake_extra_specs = {
1272 'capabilities:dedupe': '<is> True',
1273 'capabilities:compression': '<is> True',
1274 'capabilities:huawei_smartcache': '<is> False',
1275 'huawei_smartcache:cachename': None,
1276 'capabilities:huawei_smartpartition': '<is> False',
1277 'huawei_smartpartition:partitionname': None,
1278 'capabilities:thin_provisioning': '<is> False',
1279 'test:test:test': 'test',
1280 }
1282 fake_share_type_id = 'fooid-4'
1283 self.fake_type_thin_extra = {
1284 'test_with_extra': {
1285 'created_at': 'fake_time',
1286 'deleted': '0',
1287 'deleted_at': None,
1288 'extra_specs': fake_extra_specs,
1289 'required_extra_specs': {},
1290 'id': fake_share_type_id,
1291 'name': 'test_with_extra',
1292 'updated_at': None
1293 }
1294 }
1296 self.share_nfs_host_not_exist = {
1297 'id': 'fake_uuid',
1298 'project_id': 'fake_tenant_id',
1299 'display_name': 'fake',
1300 'name': 'share-fake-uuid',
1301 'size': 1,
1302 'share_proto': 'NFS',
1303 'share_network_id': 'fake_net_id',
1304 'share_server_id': 'fake-share-srv-id',
1305 'host': 'fake_host@fake_backend#',
1306 }
1308 self.share_nfs_storagepool_fail = {
1309 'id': 'fake_uuid',
1310 'project_id': 'fake_tenant_id',
1311 'display_name': 'fake',
1312 'name': 'share-fake-uuid',
1313 'size': 1,
1314 'share_proto': 'NFS',
1315 'share_network_id': 'fake_net_id',
1316 'share_server_id': 'fake-share-srv-id',
1317 'host': 'fake_host@fake_backend#OpenStack_Pool2',
1318 }
1320 fake_extra_specs = {
1321 'driver_handles_share_servers': 'False',
1322 }
1323 fake_share_type_id = 'fake_id'
1324 self.fake_type_extra = {
1325 'test_with_extra': {
1326 'created_at': 'fake_time',
1327 'deleted': '0',
1328 'deleted_at': None,
1329 'extra_specs': fake_extra_specs,
1330 'required_extra_specs': {},
1331 'id': fake_share_type_id,
1332 'name': 'test_with_extra',
1333 'updated_at': None
1334 }
1335 }
1337 self.active_replica = {
1338 'id': 'fake_active_replica_id',
1339 'share_id': 'fake_share_id',
1340 'name': 'share_fake_uuid',
1341 'host': 'hostname1@backend_name1#OpenStack_Pool',
1342 'size': 5,
1343 'share_proto': 'NFS',
1344 'replica_state': common_constants.REPLICA_STATE_ACTIVE,
1345 }
1347 self.new_replica = {
1348 'id': 'fake_new_replica_id',
1349 'share_id': 'fake_share_id',
1350 'name': 'share_fake_new_uuid',
1351 'host': 'hostname2@backend_name2#OpenStack_Pool',
1352 'size': 5,
1353 'share_proto': 'NFS',
1354 'replica_state': common_constants.REPLICA_STATE_OUT_OF_SYNC,
1355 'share_type_id': 'fake_id',
1356 }
1358 def _get_share_by_proto(self, share_proto):
1359 if share_proto == "NFS":
1360 share = self.share_nfs
1361 elif share_proto == "CIFS": 1361 ↛ 1364line 1361 didn't jump to line 1364 because the condition on line 1361 was always true
1362 share = self.share_cifs
1363 else:
1364 share = None
1365 return share
1367 def mock_share_type(self, share_type):
1368 self.mock_object(db,
1369 'share_type_get',
1370 mock.Mock(return_value=share_type))
1372 def test_no_configuration(self):
1373 self.mock_object(huawei_nas.HuaweiNasDriver,
1374 'driver_handles_share_servers',
1375 True)
1377 self.assertRaises(exception.InvalidInput,
1378 huawei_nas.HuaweiNasDriver)
1380 def test_conf_product_fail(self):
1381 self.recreate_fake_conf_file(product_flag=False)
1382 self.driver.plugin.configuration.manila_huawei_conf_file = (
1383 self.fake_conf_file)
1384 self.assertRaises(exception.InvalidInput,
1385 self.driver.plugin.check_conf_file)
1387 def test_conf_pool_node_fail(self):
1388 self.recreate_fake_conf_file(pool_node_flag=False)
1389 self.driver.plugin.configuration.manila_huawei_conf_file = (
1390 self.fake_conf_file)
1391 self.assertRaises(exception.InvalidInput,
1392 self.driver.plugin.check_conf_file)
1394 def test_conf_username_fail(self):
1395 self.recreate_fake_conf_file(username_flag=False)
1396 self.driver.plugin.configuration.manila_huawei_conf_file = (
1397 self.fake_conf_file)
1398 self.assertRaises(exception.InvalidInput,
1399 self.driver.plugin.check_conf_file)
1401 def test_conf_timeout_fail(self):
1402 self.recreate_fake_conf_file(timeout_flag=False)
1403 self.driver.plugin.configuration.manila_huawei_conf_file = (
1404 self.fake_conf_file)
1405 timeout = self.driver.plugin._get_timeout()
1406 self.assertEqual(60, timeout)
1408 def test_conf_wait_interval_fail(self):
1409 self.recreate_fake_conf_file(wait_interval_flag=False)
1410 self.driver.plugin.configuration.manila_huawei_conf_file = (
1411 self.fake_conf_file)
1412 wait_interval = self.driver.plugin._get_wait_interval()
1413 self.assertEqual(3, wait_interval)
1415 def test_conf_logical_ip_fail(self):
1416 self.configuration.driver_handles_share_servers = True
1417 self.recreate_fake_conf_file(logical_port="fake_port")
1418 self.driver.plugin.configuration.manila_huawei_conf_file = (
1419 self.fake_conf_file)
1420 self.configuration.driver_handles_share_servers = False
1421 self.assertRaises(exception.InvalidInput,
1422 self.driver.plugin.check_conf_file)
1424 def test_conf_snapshot_replication_conflict(self):
1425 self.recreate_fake_conf_file(snapshot_support=True,
1426 replication_support=True)
1427 self.driver.plugin.configuration.manila_huawei_conf_file = (
1428 self.fake_conf_file)
1429 self.driver.plugin._setup_conf()
1430 self.assertRaises(exception.BadConfigurationException,
1431 self.driver.plugin.check_conf_file)
1433 def test_get_backend_driver_fail(self):
1434 test_fake_conf_file = None
1435 self.driver.plugin.configuration.manila_huawei_conf_file = (
1436 test_fake_conf_file)
1437 self.assertRaises(exception.InvalidInput,
1438 self.driver.get_backend_driver)
1440 def test_get_backend_driver_fail_driver_none(self):
1441 self.recreate_fake_conf_file(product_flag=False)
1442 self.driver.plugin.configuration.manila_huawei_conf_file = (
1443 self.fake_conf_file)
1444 self.assertRaises(exception.InvalidInput,
1445 self.driver.get_backend_driver)
1447 def test_create_share_storagepool_not_exist(self):
1448 self.driver.plugin.helper.login()
1449 self.assertRaises(exception.InvalidHost,
1450 self.driver.create_share,
1451 self._context,
1452 self.share_nfs_host_not_exist,
1453 self.share_server)
1455 def test_create_share_nfs_storagepool_fail(self):
1456 self.driver.plugin.helper.login()
1457 self.assertRaises(exception.InvalidHost,
1458 self.driver.create_share,
1459 self._context,
1460 self.share_nfs_storagepool_fail,
1461 self.share_server)
1463 def test_create_share_nfs_no_data_fail(self):
1464 self.driver.plugin.helper.create_share_data_flag = True
1465 self.driver.plugin.helper.login()
1466 self.assertRaises(exception.InvalidShare,
1467 self.driver.create_share,
1468 self._context,
1469 self.share_nfs,
1470 self.share_server)
1472 def test_read_xml_fail(self):
1473 test_fake_conf_file = None
1474 self.driver.plugin.configuration.manila_huawei_conf_file = (
1475 test_fake_conf_file)
1476 self.assertRaises(exception.InvalidInput,
1477 self.driver.plugin.helper._read_xml)
1479 def test_connect_success(self):
1480 FakeRpcServer.start = mock.Mock()
1481 rpc.get_server = mock.Mock(return_value=FakeRpcServer())
1482 self.driver.plugin.connect()
1483 FakeRpcServer.start.assert_called_once()
1485 def test_connect_fail(self):
1486 self.driver.plugin.helper.test_multi_url_flag = 1
1487 self.assertRaises(exception.InvalidShare,
1488 self.driver.plugin.connect)
1490 def test_login_success(self):
1491 deviceid = self.driver.plugin.helper.login()
1492 self.assertEqual("210235G7J20000000000", deviceid)
1494 def test_check_for_setup_success(self):
1495 self.driver.plugin.helper.login()
1496 self.driver.check_for_setup_error()
1498 def test_check_for_setup_service_down(self):
1499 self.driver.plugin.helper.service_status_flag = False
1500 self.driver.plugin.helper.login()
1501 self.driver.check_for_setup_error()
1503 def test_check_for_setup_nfs_down(self):
1504 self.driver.plugin.helper.service_nfs_status_flag = False
1505 self.driver.plugin.helper.login()
1506 self.driver.check_for_setup_error()
1508 def test_check_for_setup_service_false(self):
1509 self.driver.plugin.helper.login()
1510 self.driver.plugin.helper.test_normal = False
1511 self.assertRaises(exception.InvalidShare,
1512 self.driver.check_for_setup_error)
1514 def test_create_share_no_extra(self):
1515 share_type = self.fake_type_not_extra['test_with_extra']
1516 self.mock_object(db,
1517 'share_type_get',
1518 mock.Mock(return_value=share_type))
1519 location = self.driver.create_share(self._context, self.share_nfs,
1520 self.share_server)
1521 self.assertEqual("100.115.10.68:/share_fake_uuid", location)
1522 self.assertEqual(constants.ALLOC_TYPE_THIN_FLAG,
1523 self.driver.plugin.helper.alloc_type)
1525 def test_create_share_with_extra_thin(self):
1526 share_type = {
1527 'extra_specs': {
1528 'capabilities:thin_provisioning': '<is> True'
1529 },
1530 }
1531 self.mock_object(db,
1532 'share_type_get',
1533 mock.Mock(return_value=share_type))
1534 self.driver.plugin.helper.login()
1535 location = self.driver.create_share(self._context, self.share_nfs,
1536 self.share_server)
1537 self.assertEqual("100.115.10.68:/share_fake_uuid", location)
1538 self.assertEqual(constants.ALLOC_TYPE_THIN_FLAG,
1539 self.driver.plugin.helper.alloc_type)
1541 def test_create_share_with_extra_thick(self):
1542 share_type = {
1543 'extra_specs': {
1544 'capabilities:thin_provisioning': '<is> False'
1545 },
1546 }
1547 self.mock_object(db,
1548 'share_type_get',
1549 mock.Mock(return_value=share_type))
1550 self.driver.plugin.helper.login()
1551 location = self.driver.create_share(self._context, self.share_nfs,
1552 self.share_server)
1553 self.assertEqual("100.115.10.68:/share_fake_uuid", location)
1554 self.assertEqual(constants.ALLOC_TYPE_THICK_FLAG,
1555 self.driver.plugin.helper.alloc_type)
1557 @ddt.data(*constants.VALID_SECTOR_SIZES)
1558 def test_create_share_with_sectorsize_in_type(self, sectorsize):
1559 share_type = {
1560 'extra_specs': {
1561 'capabilities:huawei_sectorsize': "<is> true",
1562 'huawei_sectorsize:sectorsize': sectorsize,
1563 },
1564 }
1565 self.mock_share_type(share_type)
1567 self.driver.plugin.helper.login()
1568 location = self.driver.create_share(self._context, self.share_nfs,
1569 self.share_server)
1571 self.assertEqual("100.115.10.68:/share_fake_uuid", location)
1572 self.assertTrue(db.share_type_get.called)
1574 @ddt.data('128', 'xx', 'None', ' ')
1575 def test_create_share_with_illegal_sectorsize_in_type(self, sectorsize):
1576 share_type = {
1577 'extra_specs': {
1578 'capabilities:huawei_sectorsize': "<is> true",
1579 'huawei_sectorsize:sectorsize': sectorsize,
1580 },
1581 }
1582 self.mock_share_type(share_type)
1584 self.driver.plugin.helper.login()
1585 self.assertRaises(exception.InvalidShare,
1586 self.driver.create_share,
1587 self._context,
1588 self.share_nfs,
1589 self.share_server)
1591 @ddt.data({'extra_specs': {'capabilities:huawei_sectorsize': "<is> false",
1592 'huawei_sectorsize:sectorsize': '0'}, 'xmlvalue': '4'},
1593 {'extra_specs': {'capabilities:huawei_sectorsize': "<is> False",
1594 'huawei_sectorsize:sectorsize': '128'}, 'xmlvalue': '8'},
1595 {'extra_specs': {'capabilities:huawei_sectorsize': "false",
1596 'huawei_sectorsize:sectorsize': 'a'}, 'xmlvalue': '16'},
1597 {'extra_specs': {'capabilities:huawei_sectorsize': "False",
1598 'huawei_sectorsize:sectorsize': 'xx'}, 'xmlvalue': '32'},
1599 {'extra_specs': {'capabilities:huawei_sectorsize': "true",
1600 'huawei_sectorsize:sectorsize': 'None'}, 'xmlvalue': '64'},
1601 {'extra_specs': {'capabilities:huawei_sectorsize': "True",
1602 'huawei_sectorsize:sectorsize': ' '}, 'xmlvalue': ' '},
1603 {'extra_specs': {'capabilities:huawei_sectorsize': "True",
1604 'huawei_sectorsize:sectorsize': ''}, 'xmlvalue': ''})
1605 @ddt.unpack
1606 def test_create_share_with_invalid_type_valid_xml(self, extra_specs,
1607 xmlvalue):
1608 fake_share_type = {}
1609 fake_share_type['extra_specs'] = extra_specs
1610 self.mock_share_type(fake_share_type)
1612 self.recreate_fake_conf_file(sectorsize_value=xmlvalue)
1613 self.driver.plugin.configuration.manila_huawei_conf_file = (
1614 self.fake_conf_file)
1615 self.driver.plugin.helper.login()
1616 location = self.driver.create_share(self._context, self.share_nfs,
1617 self.share_server)
1619 self.assertEqual("100.115.10.68:/share_fake_uuid", location)
1620 self.assertTrue(db.share_type_get.called)
1622 @ddt.data({'extra_specs': {'capabilities:huawei_sectorsize': "<is> false",
1623 'huawei_sectorsize:sectorsize': '4'}, 'xmlvalue': '0'},
1624 {'extra_specs': {'capabilities:huawei_sectorsize': "<is> False",
1625 'huawei_sectorsize:sectorsize': '8'}, 'xmlvalue': '128'},
1626 {'extra_specs': {'capabilities:huawei_sectorsize': "false",
1627 'huawei_sectorsize:sectorsize': '16'}, 'xmlvalue': 'a'},
1628 {'extra_specs': {'capabilities:huawei_sectorsize': "False",
1629 'huawei_sectorsize:sectorsize': '32'}, 'xmlvalue': 'xx'},
1630 {'extra_specs': {'capabilities:huawei_sectorsize': "true",
1631 'huawei_sectorsize:sectorsize': '64'}, 'xmlvalue': 'None'})
1632 @ddt.unpack
1633 def test_create_share_with_invalid_type_illegal_xml(self, extra_specs,
1634 xmlvalue):
1635 fake_share_type = {}
1636 fake_share_type['extra_specs'] = extra_specs
1637 self.mock_share_type(fake_share_type)
1639 self.recreate_fake_conf_file(sectorsize_value=xmlvalue)
1640 self.driver.plugin.configuration.manila_huawei_conf_file = (
1641 self.fake_conf_file)
1642 self.driver.plugin.helper.login()
1644 self.assertRaises(exception.InvalidShare,
1645 self.driver.create_share,
1646 self._context,
1647 self.share_nfs,
1648 self.share_server)
1650 def test_shrink_share_success(self):
1651 self.driver.plugin.helper.shrink_share_flag = False
1652 self.driver.plugin.helper.login()
1653 self.driver.shrink_share(self.share_nfs, 1,
1654 self.share_server)
1655 self.assertTrue(self.driver.plugin.helper.shrink_share_flag)
1657 def test_shrink_share_fail(self):
1658 self.driver.plugin.helper.login()
1659 self.driver.plugin.helper.test_normal = False
1660 self.assertRaises(exception.InvalidShare,
1661 self.driver.shrink_share,
1662 self.share_nfs,
1663 1,
1664 self.share_server)
1666 def test_shrink_share_size_fail(self):
1667 self.driver.plugin.helper.login()
1668 self.assertRaises(exception.InvalidShare,
1669 self.driver.shrink_share,
1670 self.share_nfs,
1671 5,
1672 self.share_server)
1674 def test_shrink_share_alloctype_fail(self):
1675 self.driver.plugin.helper.login()
1676 self.driver.plugin.helper.fs_status_flag = False
1677 self.assertRaises(exception.InvalidShare,
1678 self.driver.shrink_share,
1679 self.share_nfs,
1680 1,
1681 self.share_server)
1683 def test_shrink_share_not_exist(self):
1684 self.driver.plugin.helper.login()
1685 self.driver.plugin.helper.share_exist = False
1686 self.assertRaises(exception.InvalidShare,
1687 self.driver.shrink_share,
1688 self.share_nfs,
1689 1,
1690 self.share_server)
1692 def test_extend_share_success(self):
1693 self.driver.plugin.helper.extend_share_flag = False
1694 self.driver.plugin.helper.login()
1695 self.driver.extend_share(self.share_nfs, 5,
1696 self.share_server)
1697 self.assertTrue(self.driver.plugin.helper.extend_share_flag)
1699 def test_extend_share_fail(self):
1700 self.driver.plugin.helper.login()
1701 self.assertRaises(exception.InvalidInput,
1702 self.driver.extend_share,
1703 self.share_nfs,
1704 3,
1705 self.share_server)
1707 def test_extend_share_not_exist(self):
1708 self.driver.plugin.helper.login()
1709 self.driver.plugin.helper.share_exist = False
1710 self.assertRaises(exception.InvalidShareAccess,
1711 self.driver.extend_share,
1712 self.share_nfs,
1713 4,
1714 self.share_server)
1716 def test_create_share_nfs_success(self):
1717 share_type = self.fake_type_not_extra['test_with_extra']
1718 self.mock_object(db,
1719 'share_type_get',
1720 mock.Mock(return_value=share_type))
1721 self.driver.plugin.helper.login()
1722 location = self.driver.create_share(self._context, self.share_nfs,
1723 self.share_server)
1724 self.assertEqual("100.115.10.68:/share_fake_uuid", location)
1726 def test_create_share_cifs_success(self):
1727 share_type = self.fake_type_not_extra['test_with_extra']
1728 self.mock_object(db,
1729 'share_type_get',
1730 mock.Mock(return_value=share_type))
1731 self.driver.plugin.helper.login()
1732 location = self.driver.create_share(self._context, self.share_cifs,
1733 self.share_server)
1734 self.assertEqual("\\\\100.115.10.68\\share_fake_uuid", location)
1736 def test_create_share_with_extra(self):
1737 self.driver.plugin.helper.add_fs_to_partition_flag = False
1738 self.driver.plugin.helper.add_fs_to_cache_flag = False
1739 share_type = self.fake_type_w_extra['test_with_extra']
1740 self.mock_object(db,
1741 'share_type_get',
1742 mock.Mock(return_value=share_type))
1743 location = self.driver.create_share(self._context, self.share_nfs,
1744 self.share_server)
1745 self.assertEqual("100.115.10.68:/share_fake_uuid", location)
1746 self.assertTrue(self.driver.plugin.helper.add_fs_to_partition_flag)
1747 self.assertTrue(self.driver.plugin.helper.add_fs_to_cache_flag)
1749 @ddt.data({'capabilities:dedupe': '<is> True',
1750 'capabilities:thin_provisioning': '<is> False'},
1751 {'capabilities:dedupe': '<is> True',
1752 'capabilities:compression': '<is> True',
1753 'capabilities:thin_provisioning': '<is> False'},
1754 {'capabilities:huawei_smartcache': '<is> True',
1755 'huawei_smartcache:cachename': None},
1756 {'capabilities:huawei_smartpartition': '<is> True',
1757 'huawei_smartpartition:partitionname': None},
1758 {'capabilities:huawei_smartcache': '<is> True'},
1759 {'capabilities:huawei_smartpartition': '<is> True'})
1760 def test_create_share_with_extra_error(self, fake_extra_specs):
1761 fake_share_type_id = 'fooid-2'
1762 fake_type_error_extra = {
1763 'test_with_extra': {
1764 'created_at': 'fake_time',
1765 'deleted': '0',
1766 'deleted_at': None,
1767 'extra_specs': fake_extra_specs,
1768 'required_extra_specs': {},
1769 'id': fake_share_type_id,
1770 'name': 'test_with_extra',
1771 'updated_at': None
1772 }
1773 }
1774 share_type = fake_type_error_extra['test_with_extra']
1775 self.mock_object(db,
1776 'share_type_get',
1777 mock.Mock(return_value=share_type))
1778 self.driver.plugin.helper.login()
1779 self.assertRaises(exception.InvalidShare,
1780 self.driver.create_share,
1781 self._context,
1782 self.share_nfs_thick,
1783 self.share_server)
1785 @ddt.data({"fake_extra_specs_qos": {"qos:maxIOPS": "100",
1786 "qos:maxBandWidth": "50",
1787 "qos:IOType": "0"},
1788 "fake_qos_info": {"MAXIOPS": "100",
1789 "MAXBANDWIDTH": "50",
1790 "IOTYPE": "0",
1791 "LATENCY": "0",
1792 "NAME": "OpenStack_fake_qos"}},
1793 {"fake_extra_specs_qos": {"qos:maxIOPS": "100",
1794 "qos:IOType": "1"},
1795 "fake_qos_info": {"NAME": "fake_qos",
1796 "MAXIOPS": "100",
1797 "IOTYPE": "1",
1798 "LATENCY": "0"}},
1799 {"fake_extra_specs_qos": {"qos:minIOPS": "100",
1800 "qos:minBandWidth": "50",
1801 'qos:latency': "50",
1802 "qos:IOType": "0"},
1803 "fake_qos_info": {"MINIOPS": "100",
1804 "MINBANDWIDTH": "50",
1805 "IOTYPE": "0",
1806 "LATENCY": "50",
1807 "NAME": "OpenStack_fake_qos"}})
1808 @ddt.unpack
1809 def test_create_share_with_qos(self, fake_extra_specs_qos, fake_qos_info):
1810 fake_share_type_id = 'fooid-2'
1811 fake_extra_specs = {"capabilities:qos": "<is> True"}
1812 fake_extra_specs.update(fake_extra_specs_qos)
1814 fake_type_error_extra = {
1815 'test_with_extra': {
1816 'created_at': 'fake_time',
1817 'deleted': '0',
1818 'deleted_at': None,
1819 'extra_specs': fake_extra_specs,
1820 'required_extra_specs': {},
1821 'id': fake_share_type_id,
1822 'name': 'test_with_extra',
1823 'updated_at': None
1824 }
1825 }
1827 fake_qos_info_respons = {
1828 "error": {
1829 "code": 0
1830 },
1831 "data": [{
1832 "ID": "11",
1833 "FSLIST": u'["1", "2", "3", "4"]',
1834 "LUNLIST": '[""]',
1835 "RUNNINGSTATUS": "2",
1836 }]
1837 }
1839 fake_qos_info_respons["data"][0].update(fake_qos_info)
1840 share_type = fake_type_error_extra['test_with_extra']
1841 self.mock_object(db,
1842 'share_type_get',
1843 mock.Mock(return_value=share_type))
1844 self.mock_object(helper.RestHelper,
1845 'get_qos',
1846 mock.Mock(return_value=fake_qos_info_respons))
1848 self.driver.plugin.configuration.manila_huawei_conf_file = (
1849 self.fake_conf_file)
1850 self.driver.plugin.helper.login()
1852 location = self.driver.create_share(self._context, self.share_nfs,
1853 self.share_server)
1854 self.assertEqual("100.115.10.68:/share_fake_uuid", location)
1856 @ddt.data({'capabilities:qos': '<is> True',
1857 'qos:maxIOPS': -1},
1858 {'capabilities:qos': '<is> True',
1859 'qos:IOTYPE': 4},
1860 {'capabilities:qos': '<is> True',
1861 'qos:IOTYPE': 100},
1862 {'capabilities:qos': '<is> True',
1863 'qos:maxIOPS': 0},
1864 {'capabilities:qos': '<is> True',
1865 'qos:minIOPS': 0},
1866 {'capabilities:qos': '<is> True',
1867 'qos:minBandWidth': 0},
1868 {'capabilities:qos': '<is> True',
1869 'qos:maxBandWidth': 0},
1870 {'capabilities:qos': '<is> True',
1871 'qos:latency': 0},
1872 {'capabilities:qos': '<is> True',
1873 'qos:maxIOPS': 100},
1874 {'capabilities:qos': '<is> True',
1875 'qos:maxIOPS': 100,
1876 'qos:minBandWidth': 100,
1877 'qos:IOType': '0'})
1878 def test_create_share_with_invalid_qos(self, fake_extra_specs):
1879 fake_share_type_id = 'fooid-2'
1880 fake_type_error_extra = {
1881 'test_with_extra': {
1882 'created_at': 'fake_time',
1883 'deleted': '0',
1884 'deleted_at': None,
1885 'extra_specs': fake_extra_specs,
1886 'required_extra_specs': {},
1887 'id': fake_share_type_id,
1888 'name': 'test_with_extra',
1889 'updated_at': None
1890 }
1891 }
1893 share_type = fake_type_error_extra['test_with_extra']
1894 self.mock_object(db,
1895 'share_type_get',
1896 mock.Mock(return_value=share_type))
1898 self.driver.plugin.configuration.manila_huawei_conf_file = (
1899 self.fake_conf_file)
1900 self.driver.plugin.helper.login()
1901 self.assertRaises(exception.InvalidShare,
1902 self.driver.create_share,
1903 self._context,
1904 self.share_nfs,
1905 self.share_server)
1907 def test_create_share_cache_not_exist(self):
1908 self.driver.plugin.helper.cache_exist = False
1909 share_type = self.fake_type_w_extra['test_with_extra']
1910 self.mock_object(db,
1911 'share_type_get',
1912 mock.Mock(return_value=share_type))
1913 self.driver.plugin.helper.login()
1914 self.assertRaises(exception.InvalidShare,
1915 self.driver.create_share,
1916 self._context,
1917 self.share_nfs,
1918 self.share_server)
1920 def test_add_share_to_cache_fail(self):
1921 opts = dict(
1922 huawei_smartcache='true',
1923 cachename=None,
1924 )
1925 fsid = 4
1926 smartcache = smartx.SmartCache(self.driver.plugin.helper)
1927 self.assertRaises(exception.InvalidInput, smartcache.add,
1928 opts, fsid)
1930 def test_create_share_partition_not_exist(self):
1931 self.driver.plugin.helper.partition_exist = False
1932 share_type = self.fake_type_w_extra['test_with_extra']
1933 self.mock_object(db,
1934 'share_type_get',
1935 mock.Mock(return_value=share_type))
1936 self.driver.plugin.helper.login()
1937 self.assertRaises(exception.InvalidShare,
1938 self.driver.create_share,
1939 self._context,
1940 self.share_nfs,
1941 self.share_server)
1943 def test_add_share_to_partition_fail(self):
1944 opts = dict(
1945 huawei_smartpartition='true',
1946 partitionname=None,
1947 )
1948 fsid = 4
1949 smartpartition = smartx.SmartPartition(self.driver.plugin.helper)
1950 self.assertRaises(exception.InvalidInput, smartpartition.add,
1951 opts, fsid)
1953 def test_login_fail(self):
1954 self.driver.plugin.helper.test_normal = False
1955 self.assertRaises(exception.InvalidShare,
1956 self.driver.plugin.helper.login)
1958 def test_create_share_nfs_fs_fail(self):
1959 self.driver.plugin.helper.login()
1960 self.driver.plugin.helper.test_normal = False
1961 self.assertRaises(exception.InvalidShare,
1962 self.driver.create_share,
1963 self._context,
1964 self.share_nfs,
1965 self.share_server)
1967 def test_create_share_nfs_status_fail(self):
1968 self.driver.plugin.helper.login()
1969 self.driver.plugin.helper.fs_status_flag = False
1970 self.assertRaises(exception.InvalidShare,
1971 self.driver.create_share,
1972 self._context,
1973 self.share_nfs,
1974 self.share_server)
1976 def test_create_share_cifs_fs_fail(self):
1977 self.driver.plugin.helper.login()
1978 self.driver.plugin.helper.test_normal = False
1979 self.assertRaises(exception.InvalidShare,
1980 self.driver.create_share,
1981 self._context,
1982 self.share_cifs,
1983 self.share_server)
1985 def test_create_share_cifs_fail(self):
1986 self.driver.plugin.helper.login()
1987 self.driver.plugin.helper.create_share_flag = True
1988 self.assertRaises(exception.InvalidShare,
1989 self.driver.create_share,
1990 self._context,
1991 self.share_cifs,
1992 self.share_server)
1994 def test_create_share_nfs_fail(self):
1995 self.driver.plugin.helper.login()
1996 self.driver.plugin.helper.create_share_flag = True
1997 self.assertRaises(exception.InvalidShare,
1998 self.driver.create_share,
1999 self._context,
2000 self.share_nfs,
2001 self.share_server)
2003 @ddt.data({"share_proto": "NFS",
2004 "fake_qos_info_respons": {"ID": "11", "MAXIOPS": "100",
2005 "IOType": "2",
2006 "FSLIST": u'["0", "1", "4"]'}},
2007 {"share_proto": "CIFS",
2008 "fake_qos_info_respons": {"ID": "11", "MAXIOPS": "100",
2009 "IOType": "2", "FSLIST": u'["4"]',
2010 "RUNNINGSTATUS": "2"}})
2011 @ddt.unpack
2012 def test_delete_share_success(self, share_proto, fake_qos_info_respons):
2013 self.driver.plugin.helper.login()
2014 self.driver.plugin.helper.delete_flag = False
2015 if share_proto == 'NFS':
2016 share = self.share_nfs
2017 else:
2018 share = self.share_cifs
2019 with mock.patch.object(helper.RestHelper, 'get_qos_info',
2020 return_value=fake_qos_info_respons):
2021 self.driver.delete_share(self._context,
2022 share, self.share_server)
2023 self.assertTrue(self.driver.plugin.helper.delete_flag)
2025 def test_delete_share_withoutqos_success(self):
2026 self.driver.plugin.helper.login()
2027 self.driver.plugin.helper.delete_flag = False
2028 self.driver.plugin.qos_support = True
2029 self.driver.delete_share(self._context,
2030 self.share_nfs, self.share_server)
2031 self.assertTrue(self.driver.plugin.helper.delete_flag)
2033 def test_check_snapshot_id_exist_fail(self):
2034 snapshot_id = "4@share_snapshot_not_exist"
2035 self.driver.plugin.helper.login()
2036 self.driver.plugin.helper.test_normal = False
2037 snapshot_info = self.driver.plugin.helper._get_snapshot_by_id(
2038 snapshot_id)
2039 self.assertRaises(exception.InvalidShareSnapshot,
2040 self.driver.plugin.helper._check_snapshot_id_exist,
2041 snapshot_info)
2043 def test_delete_share_nfs_fail_not_exist(self):
2044 self.driver.plugin.helper.login()
2045 self.driver.plugin.helper.delete_flag = False
2046 self.driver.plugin.helper.share_exist = False
2047 self.driver.delete_share(self._context,
2048 self.share_nfs, self.share_server)
2049 self.assertTrue(self.driver.plugin.helper.delete_flag)
2051 def test_delete_share_cifs_success(self):
2052 self.driver.plugin.helper.delete_flag = False
2054 fake_qos_info_respons = {
2055 "ID": "11",
2056 "FSLIST": u'["1", "2", "3", "4"]',
2057 "LUNLIST": '[""]',
2058 "RUNNINGSTATUS": "2",
2059 }
2061 self.mock_object(helper.RestHelper,
2062 'get_qos_info',
2063 mock.Mock(return_value=fake_qos_info_respons))
2064 self.driver.plugin.helper.login()
2065 self.driver.delete_share(self._context, self.share_cifs,
2066 self.share_server)
2067 self.assertTrue(self.driver.plugin.helper.delete_flag)
2069 def test_get_network_allocations_number_dhss_true(self):
2070 self.configuration.driver_handles_share_servers = True
2071 number = self.driver.get_network_allocations_number()
2072 self.assertEqual(1, number)
2074 def test_get_network_allocations_number_dhss_false(self):
2075 self.configuration.driver_handles_share_servers = False
2076 number = self.driver.get_network_allocations_number()
2077 self.assertEqual(0, number)
2079 def test_create_nfsshare_from_nfssnapshot_success(self):
2080 share_type = self.fake_type_not_extra['test_with_extra']
2081 self.mock_object(db,
2082 'share_type_get',
2083 mock.Mock(return_value=share_type))
2084 self.mock_object(self.driver.plugin,
2085 'mount_share_to_host',
2086 mock.Mock(return_value={}))
2087 self.mock_object(self.driver.plugin,
2088 'copy_snapshot_data',
2089 mock.Mock(return_value=True))
2090 self.mock_object(self.driver.plugin,
2091 'umount_share_from_host',
2092 mock.Mock(return_value={}))
2093 self.driver.plugin.helper.login()
2094 self.driver.plugin.helper.snapshot_flag = True
2096 location = self.driver.create_share_from_snapshot(self._context,
2097 self.share_nfs,
2098 self.nfs_snapshot,
2099 self.share_server)
2101 self.assertTrue(db.share_type_get.called)
2102 self.assertEqual(2, self.driver.plugin.
2103 mount_share_to_host.call_count)
2104 self.assertTrue(self.driver.plugin.
2105 copy_snapshot_data.called)
2106 self.assertEqual(2, self.driver.plugin.
2107 umount_share_from_host.call_count)
2108 self.assertEqual("100.115.10.68:/share_fake_uuid", location)
2110 def test_create_cifsshare_from_cifssnapshot_success(self):
2111 share_type = self.fake_type_not_extra['test_with_extra']
2112 self.mock_object(db,
2113 'share_type_get',
2114 mock.Mock(return_value=share_type))
2115 self.mock_object(self.driver.plugin,
2116 'mount_share_to_host',
2117 mock.Mock(return_value={}))
2118 self.mock_object(self.driver.plugin,
2119 'copy_snapshot_data',
2120 mock.Mock(return_value=True))
2121 self.mock_object(self.driver.plugin,
2122 'umount_share_from_host',
2123 mock.Mock(return_value={}))
2124 self.driver.plugin.helper.login()
2125 self.driver.plugin.helper.snapshot_flag = True
2127 location = self.driver.create_share_from_snapshot(self._context,
2128 self.share_cifs,
2129 self.cifs_snapshot,
2130 self.share_server)
2132 self.assertTrue(db.share_type_get.called)
2133 self.assertEqual(2, self.driver.plugin.
2134 mount_share_to_host.call_count)
2135 self.assertTrue(self.driver.plugin.
2136 copy_snapshot_data.called)
2137 self.assertEqual(2, self.driver.plugin.
2138 umount_share_from_host.call_count)
2139 self.assertEqual("\\\\100.115.10.68\\share_fake_uuid", location)
2141 def test_create_nfsshare_from_cifssnapshot_success(self):
2142 share_type = self.fake_type_not_extra['test_with_extra']
2143 self.mock_object(db,
2144 'share_type_get',
2145 mock.Mock(return_value=share_type))
2146 self.mock_object(self.driver.plugin,
2147 '_get_access_id',
2148 mock.Mock(return_value={}))
2149 self.mock_object(self.driver.plugin,
2150 'mount_share_to_host',
2151 mock.Mock(return_value={}))
2152 self.mock_object(self.driver.plugin,
2153 'copy_snapshot_data',
2154 mock.Mock(return_value=True))
2155 self.mock_object(self.driver.plugin,
2156 'umount_share_from_host',
2157 mock.Mock(return_value={}))
2158 self.driver.plugin.helper.login()
2159 self.driver.plugin.helper.access_id = None
2160 self.driver.plugin.helper.snapshot_flag = True
2162 location = self.driver.create_share_from_snapshot(self._context,
2163 self.share_nfs,
2164 self.cifs_snapshot,
2165 self.share_server)
2167 self.assertTrue(db.share_type_get.called)
2168 self.assertTrue(self.driver.plugin.
2169 _get_access_id.called)
2170 self.assertEqual(2, self.driver.plugin.
2171 mount_share_to_host.call_count)
2172 self.assertTrue(self.driver.plugin.
2173 copy_snapshot_data.called)
2174 self.assertEqual(2, self.driver.plugin.
2175 umount_share_from_host.call_count)
2176 self.assertEqual("100.115.10.68:/share_fake_uuid", location)
2178 def test_create_cifsshare_from_nfssnapshot_success(self):
2179 share_type = self.fake_type_not_extra['test_with_extra']
2181 self.mock_object(db,
2182 'share_type_get',
2183 mock.Mock(return_value=share_type))
2184 self.mock_object(self.driver.plugin,
2185 '_get_access_id',
2186 mock.Mock(return_value={}))
2187 self.mock_object(utils,
2188 'execute',
2189 mock.Mock(return_value=("", "")))
2190 self.driver.plugin.helper.login()
2191 self.driver.plugin.helper.snapshot_flag = True
2193 location = self.driver.create_share_from_snapshot(self._context,
2194 self.share_cifs,
2195 self.nfs_snapshot,
2196 self.share_server)
2198 self.assertTrue(db.share_type_get.called)
2199 self.assertTrue(self.driver.plugin.
2200 _get_access_id.called)
2201 self.assertEqual(7, utils.execute.call_count)
2202 self.assertEqual("\\\\100.115.10.68\\share_fake_uuid", location)
2204 def test_create_share_from_snapshot_nonefs(self):
2205 self.driver.plugin.helper.login()
2206 self.mock_object(self.driver.plugin.helper,
2207 'get_fsid_by_name',
2208 mock.Mock(return_value={}))
2209 self.assertRaises(exception.StorageResourceNotFound,
2210 self.driver.create_share_from_snapshot,
2211 self._context, self.share_nfs,
2212 self.nfs_snapshot, self.share_server)
2213 self.assertTrue(self.driver.plugin.helper.
2214 get_fsid_by_name.called)
2216 def test_create_share_from_notexistingsnapshot_fail(self):
2217 self.driver.plugin.helper.login()
2218 self.driver.plugin.helper.snapshot_flag = False
2219 self.assertRaises(exception.ShareSnapshotNotFound,
2220 self.driver.create_share_from_snapshot,
2221 self._context, self.share_nfs,
2222 self.nfs_snapshot, self.share_server)
2224 def test_create_share_from_share_fail(self):
2225 self.driver.plugin.helper.login()
2226 self.driver.plugin.helper.snapshot_flag = True
2227 self.mock_object(self.driver.plugin,
2228 'check_fs_status',
2229 mock.Mock(return_value={}))
2230 self.assertRaises(exception.StorageResourceException,
2231 self.driver.create_share_from_snapshot,
2232 self._context, self.share_nfs,
2233 self.nfs_snapshot, self.share_server)
2234 self.assertTrue(self.driver.plugin.check_fs_status.called)
2236 def test_create_share_from_snapshot_share_error(self):
2237 self.mock_object(self.driver.plugin,
2238 '_get_share_proto',
2239 mock.Mock(return_value={}))
2240 self.driver.plugin.helper.login()
2241 self.driver.plugin.helper.snapshot_flag = True
2242 self.assertRaises(exception.ShareResourceNotFound,
2243 self.driver.create_share_from_snapshot,
2244 self._context, self.share_nfs,
2245 self.nfs_snapshot, self.share_server)
2246 self.assertTrue(self.driver.plugin.
2247 _get_share_proto.called)
2249 def test_create_share_from_snapshot_allow_oldaccess_fail(self):
2250 share_type = self.fake_type_not_extra['test_with_extra']
2251 self.mock_object(db,
2252 'share_type_get',
2253 mock.Mock(return_value=share_type))
2254 self.mock_object(self.driver.plugin,
2255 '_get_share_proto',
2256 mock.Mock(return_value='NFS'))
2257 self.mock_object(self.driver.plugin,
2258 '_get_access_id',
2259 mock.Mock(return_value={}))
2260 self.mock_object(self.driver.plugin.helper,
2261 '_get_share_by_name',
2262 mock.Mock(return_value={}))
2263 self.driver.plugin.helper.login()
2264 self.driver.plugin.helper.snapshot_flag = True
2266 self.assertRaises(exception.ShareResourceNotFound,
2267 self.driver.create_share_from_snapshot,
2268 self._context, self.share_nfs,
2269 self.nfs_snapshot, self.share_server)
2270 self.assertTrue(db.share_type_get.called)
2271 self.assertTrue(self.driver.plugin._get_share_proto.called)
2272 self.assertTrue(self.driver.plugin._get_access_id.called)
2273 self.assertTrue(self.driver.plugin.helper._get_share_by_name.called)
2275 def test_create_share_from_snapshot_mountshare_fail(self):
2276 share_type = self.fake_type_not_extra['test_with_extra']
2277 self.mock_object(db,
2278 'share_type_get',
2279 mock.Mock(return_value=share_type))
2280 self.mock_object(self.driver.plugin,
2281 'mount_share_to_host',
2282 mock.Mock(side_effect=exception.
2283 ShareMountException('err')))
2284 self.driver.plugin.helper.login()
2285 self.driver.plugin.helper.snapshot_flag = True
2287 self.assertRaises(exception.ShareMountException,
2288 self.driver.create_share_from_snapshot,
2289 self._context, self.share_nfs,
2290 self.nfs_snapshot, self.share_server)
2291 self.assertTrue(db.share_type_get.called)
2292 self.assertEqual(1, self.driver.plugin.
2293 mount_share_to_host.call_count)
2295 def test_create_share_from_snapshot_allow_newaccess_fail(self):
2296 share_type = self.fake_type_not_extra['test_with_extra']
2297 self.mock_object(db,
2298 'share_type_get',
2299 mock.Mock(return_value=share_type))
2300 self.mock_object(self.driver.plugin,
2301 '_get_share_proto',
2302 mock.Mock(return_value='NFS'))
2303 self.mock_object(self.driver.plugin,
2304 '_get_access_id',
2305 mock.Mock(return_value='5'))
2306 self.mock_object(self.driver.plugin,
2307 'mount_share_to_host',
2308 mock.Mock(return_value={}))
2309 self.mock_object(self.driver.plugin.helper,
2310 '_get_share_by_name',
2311 mock.Mock(return_value={}))
2312 self.mock_object(self.driver.plugin,
2313 'umount_share_from_host',
2314 mock.Mock(return_value={}))
2315 self.driver.plugin.helper.login()
2316 self.driver.plugin.helper.snapshot_flag = True
2318 self.assertRaises(exception.ShareResourceNotFound,
2319 self.driver.create_share_from_snapshot,
2320 self._context, self.share_nfs,
2321 self.nfs_snapshot, self.share_server)
2322 self.assertTrue(db.share_type_get.called)
2323 self.assertTrue(self.driver.plugin._get_share_proto.called)
2324 self.assertTrue(self.driver.plugin._get_access_id.called)
2325 self.assertEqual(1, self.driver.plugin.
2326 mount_share_to_host.call_count)
2327 self.assertTrue(self.driver.plugin.helper.
2328 _get_share_by_name.called)
2329 self.assertEqual(1, self.driver.plugin.
2330 umount_share_from_host.call_count)
2332 def test_create_nfsshare_from_nfssnapshot_copydata_fail(self):
2333 share_type = self.fake_type_not_extra['test_with_extra']
2334 self.mock_object(db,
2335 'share_type_get',
2336 mock.Mock(return_value=share_type))
2337 self.mock_object(self.driver.plugin,
2338 'mount_share_to_host',
2339 mock.Mock(return_value={}))
2340 self.mock_object(data_utils,
2341 'Copy',
2342 mock.Mock(side_effect=Exception('err')))
2343 self.mock_object(utils,
2344 'execute',
2345 mock.Mock(return_value={}))
2346 self.driver.plugin.helper.login()
2347 self.driver.plugin.helper.snapshot_flag = True
2349 self.assertRaises(exception.ShareCopyDataException,
2350 self.driver.create_share_from_snapshot,
2351 self._context, self.share_nfs,
2352 self.nfs_snapshot, self.share_server)
2353 self.assertTrue(db.share_type_get.called)
2354 self.assertEqual(2, self.driver.plugin.
2355 mount_share_to_host.call_count)
2356 self.assertTrue(data_utils.Copy.called)
2357 self.assertEqual(2, utils.execute.call_count)
2359 def test_create_nfsshare_from_nfssnapshot_umountshare_fail(self):
2360 share_type = self.fake_type_not_extra['test_with_extra']
2361 self.mock_object(db,
2362 'share_type_get',
2363 mock.Mock(return_value=share_type))
2364 self.mock_object(self.driver.plugin,
2365 'mount_share_to_host',
2366 mock.Mock(return_value={}))
2367 self.mock_object(self.driver.plugin,
2368 'copy_snapshot_data',
2369 mock.Mock(return_value=True))
2370 self.mock_object(self.driver.plugin,
2371 'umount_share_from_host',
2372 mock.Mock(side_effect=exception.
2373 ShareUmountException('err')))
2374 self.mock_object(os, 'rmdir',
2375 mock.Mock(side_effect=Exception('err')))
2376 self.driver.plugin.helper.login()
2377 self.driver.plugin.helper.snapshot_flag = True
2379 location = self.driver.create_share_from_snapshot(self._context,
2380 self.share_nfs,
2381 self.cifs_snapshot,
2382 self.share_server)
2384 self.assertTrue(db.share_type_get.called)
2385 self.assertEqual(2, self.driver.plugin.
2386 mount_share_to_host.call_count)
2387 self.assertTrue(self.driver.plugin.copy_snapshot_data.called)
2388 self.assertEqual(2, self.driver.plugin.
2389 umount_share_from_host.call_count)
2390 self.assertTrue(os.rmdir.called)
2391 self.assertEqual("100.115.10.68:/share_fake_uuid", location)
2393 def test_get_share_stats_refresh_pool_not_exist(self):
2394 self.recreate_fake_conf_file(pool_node_flag=False)
2395 self.driver.plugin.configuration.manila_huawei_conf_file = (
2396 self.fake_conf_file)
2397 self.assertRaises(exception.InvalidInput,
2398 self.driver._update_share_stats)
2400 @ddt.data({"snapshot_support": True,
2401 "replication_support": False},
2402 {"snapshot_support": False,
2403 "replication_support": True})
2404 @ddt.unpack
2405 def test_get_share_stats_refresh(self, snapshot_support,
2406 replication_support):
2407 self.recreate_fake_conf_file(snapshot_support=snapshot_support,
2408 replication_support=replication_support)
2409 self.driver.plugin.configuration.manila_huawei_conf_file = (
2410 self.fake_conf_file)
2412 self.driver.plugin._setup_conf()
2413 self.driver._update_share_stats()
2415 expected = {
2416 "share_backend_name": "fake_share_backend_name",
2417 "driver_handles_share_servers": False,
2418 "vendor_name": "Huawei",
2419 "driver_version": "1.3",
2420 "storage_protocol": "NFS_CIFS",
2421 "reserved_percentage": 0,
2422 'reserved_snapshot_percentage': 0,
2423 'reserved_share_extend_percentage': 0,
2424 "total_capacity_gb": 0.0,
2425 "free_capacity_gb": 0.0,
2426 "qos": True,
2427 "snapshot_support": snapshot_support,
2428 "create_share_from_snapshot_support": snapshot_support,
2429 "revert_to_snapshot_support": snapshot_support,
2430 "mount_snapshot_support": False,
2431 "replication_domain": None,
2432 "filter_function": None,
2433 "goodness_function": None,
2434 'mount_point_name_support': False,
2435 "pools": [],
2436 "share_group_stats": {"consistent_snapshot_support": None},
2437 "ipv4_support": True,
2438 "ipv6_support": False,
2439 "security_service_update_support": False,
2440 "share_server_multiple_subnet_support": False,
2441 "network_allocation_update_support": False,
2442 "share_replicas_migration_support": False,
2443 'encryption_support': None,
2444 }
2446 if replication_support:
2447 expected['replication_type'] = 'dr'
2449 pool = dict(
2450 pool_name='OpenStack_Pool',
2451 total_capacity_gb=2.0,
2452 free_capacity_gb=1.0,
2453 allocated_capacity_gb=1.0,
2454 qos=True,
2455 reserved_percentage=0,
2456 reserved_snapshot_percentage=0,
2457 reserved_share_extend_percentage=0,
2458 compression=[True, False],
2459 dedupe=[True, False],
2460 max_over_subscription_ratio=1,
2461 provisioned_capacity_gb=1.0,
2462 thin_provisioning=[True, False],
2463 huawei_smartcache=[True, False],
2464 huawei_smartpartition=[True, False],
2465 huawei_sectorsize=[True, False],
2466 huawei_disk_type='ssd',
2467 )
2468 expected["pools"].append(pool)
2469 self.assertEqual(expected, self.driver._stats)
2471 @ddt.data({'TIER0CAPACITY': '100',
2472 'TIER1CAPACITY': '0',
2473 'TIER2CAPACITY': '0',
2474 'disktype': 'ssd'},
2475 {'TIER0CAPACITY': '0',
2476 'TIER1CAPACITY': '100',
2477 'TIER2CAPACITY': '0',
2478 'disktype': 'sas'},
2479 {'TIER0CAPACITY': '0',
2480 'TIER1CAPACITY': '0',
2481 'TIER2CAPACITY': '100',
2482 'disktype': 'nl_sas'},
2483 {'TIER0CAPACITY': '100',
2484 'TIER1CAPACITY': '100',
2485 'TIER2CAPACITY': '100',
2486 'disktype': 'mix'},
2487 {'TIER0CAPACITY': '0',
2488 'TIER1CAPACITY': '0',
2489 'TIER2CAPACITY': '0',
2490 'disktype': ''})
2491 def test_get_share_stats_disk_type(self, disk_type_value):
2492 self.driver.plugin.helper.login()
2493 storage_pool_info = {"error": {"code": 0},
2494 "data": [{"USERFREECAPACITY": "2097152",
2495 "ID": "1",
2496 "NAME": "OpenStack_Pool",
2497 "USERTOTALCAPACITY": "4194304",
2498 "USAGETYPE": "2",
2499 "USERCONSUMEDCAPACITY": "2097152"}]}
2500 storage_pool_info['data'][0]['TIER0CAPACITY'] = (
2501 disk_type_value['TIER0CAPACITY'])
2502 storage_pool_info['data'][0]['TIER1CAPACITY'] = (
2503 disk_type_value['TIER1CAPACITY'])
2504 storage_pool_info['data'][0]['TIER2CAPACITY'] = (
2505 disk_type_value['TIER2CAPACITY'])
2506 self.mock_object(self.driver.plugin.helper, '_find_all_pool_info',
2507 mock.Mock(return_value=storage_pool_info))
2508 self.driver._update_share_stats()
2510 if disk_type_value['disktype']:
2511 self.assertEqual(
2512 disk_type_value['disktype'],
2513 self.driver._stats['pools'][0]['huawei_disk_type'])
2514 else:
2515 self.assertIsNone(
2516 self.driver._stats['pools'][0].get('huawei_disk_type'))
2518 def test_get_disk_type_pool_info_none(self):
2519 self.driver.plugin.helper.login()
2520 self.mock_object(self.driver.plugin.helper, '_find_pool_info',
2521 mock.Mock(return_value=None))
2522 self.assertRaises(exception.InvalidInput,
2523 self.driver._update_share_stats)
2525 def test_allow_access_proto_fail(self):
2526 self.driver.plugin.helper.login()
2527 self.assertRaises(exception.InvalidInput,
2528 self.driver.allow_access,
2529 self._context,
2530 self.share_proto_fail,
2531 self.access_ip,
2532 self.share_server)
2534 def test_allow_access_ip_rw_success(self):
2535 self.driver.plugin.helper.login()
2536 self.allow_flag = False
2537 self.allow_rw_flag = False
2538 self.driver.allow_access(self._context,
2539 self.share_nfs,
2540 self.access_ip,
2541 self.share_server)
2542 self.assertTrue(self.driver.plugin.helper.allow_flag)
2543 self.assertTrue(self.driver.plugin.helper.allow_rw_flag)
2545 def test_allow_access_ip_ro_success(self):
2546 access_ro = {
2547 'access_type': 'ip',
2548 'access_to': '1.2.3.4',
2549 'access_level': 'ro',
2550 }
2552 self.driver.plugin.helper.login()
2553 self.allow_flag = False
2554 self.allow_ro_flag = False
2555 self.driver.allow_access(self._context,
2556 self.share_nfs,
2557 access_ro,
2558 self.share_server)
2559 self.assertTrue(self.driver.plugin.helper.allow_flag)
2560 self.assertTrue(self.driver.plugin.helper.allow_ro_flag)
2562 def test_allow_access_nfs_user_success(self):
2563 self.driver.plugin.helper.login()
2564 self.allow_flag = False
2565 self.allow_rw_flag = False
2566 self.driver.allow_access(self._context,
2567 self.share_nfs,
2568 self.access_user,
2569 self.share_server)
2570 self.assertTrue(self.driver.plugin.helper.allow_flag)
2571 self.assertTrue(self.driver.plugin.helper.allow_rw_flag)
2573 @ddt.data(
2574 {
2575 'access_type': 'user',
2576 'access_to': 'user_name',
2577 'access_level': 'rw',
2578 },
2579 {
2580 'access_type': 'user',
2581 'access_to': 'group_name',
2582 'access_level': 'rw',
2583 },
2584 {
2585 'access_type': 'user',
2586 'access_to': 'domain\\user_name',
2587 'access_level': 'rw',
2588 },
2589 {
2590 'access_type': 'user',
2591 'access_to': 'domain\\group_name',
2592 'access_level': 'rw',
2593 },
2594 )
2595 def test_allow_access_cifs_rw_success(self, access_user):
2596 self.driver.plugin.helper.login()
2597 self.allow_flag = False
2598 self.allow_rw_flag = False
2599 self.driver.allow_access(self._context, self.share_cifs,
2600 access_user, self.share_server)
2601 self.assertTrue(self.driver.plugin.helper.allow_flag)
2602 self.assertTrue(self.driver.plugin.helper.allow_rw_flag)
2604 def test_allow_access_cifs_user_ro_success(self):
2605 access_ro = {
2606 'access_type': 'user',
2607 'access_to': 'user_name',
2608 'access_level': 'ro',
2609 }
2611 self.driver.plugin.helper.login()
2612 self.allow_flag = False
2613 self.allow_ro_flag = False
2614 self.driver.allow_access(self._context, self.share_cifs,
2615 access_ro, self.share_server)
2616 self.assertTrue(self.driver.plugin.helper.allow_flag)
2617 self.assertTrue(self.driver.plugin.helper.allow_ro_flag)
2619 def test_allow_access_level_fail(self):
2620 access_fail = {
2621 'access_type': 'user',
2622 'access_to': 'user_name',
2623 'access_level': 'fail',
2624 }
2626 self.driver.plugin.helper.login()
2627 self.assertRaises(exception.InvalidShareAccess,
2628 self.driver.allow_access,
2629 self._context, self.share_cifs,
2630 access_fail, self.share_server)
2632 def test_update_access_add_delete(self):
2633 self.driver.plugin.helper.login()
2634 self.allow_flag = False
2635 self.allow_rw_flag = False
2636 self.deny_flag = False
2637 add_rules = [self.access_ip]
2638 delete_rules = [self.access_ip_exist]
2639 self.driver.update_access(self._context,
2640 self.share_nfs,
2641 None,
2642 add_rules,
2643 delete_rules,
2644 self.share_server)
2645 self.assertTrue(self.driver.plugin.helper.allow_flag)
2646 self.assertTrue(self.driver.plugin.helper.allow_rw_flag)
2647 self.assertTrue(self.driver.plugin.helper.deny_flag)
2649 def test_update_access_nfs(self):
2650 self.driver.plugin.helper.login()
2651 self.allow_flag = False
2652 self.allow_rw_flag = False
2653 rules = [self.access_ip, self.access_ip_exist]
2654 self.driver.update_access(self._context,
2655 self.share_nfs,
2656 rules,
2657 None,
2658 None,
2659 self.share_server)
2660 self.assertTrue(self.driver.plugin.helper.allow_flag)
2661 self.assertTrue(self.driver.plugin.helper.allow_rw_flag)
2663 def test_update_access_cifs(self):
2664 self.driver.plugin.helper.login()
2665 self.allow_flag = False
2666 self.allow_rw_flag = False
2667 rules = [self.access_user, self.access_user_exist]
2668 self.driver.update_access(self._context,
2669 self.share_cifs,
2670 rules,
2671 None,
2672 None,
2673 self.share_server)
2674 self.assertTrue(self.driver.plugin.helper.allow_flag)
2675 self.assertTrue(self.driver.plugin.helper.allow_rw_flag)
2677 def test_update_access_rules_share_not_exist(self):
2678 self.driver.plugin.helper.login()
2679 rules = [self.access_ip]
2680 self.driver.plugin.helper.share_exist = False
2681 self.assertRaises(exception.ShareResourceNotFound,
2682 self.driver.update_access, self._context,
2683 self.share_nfs, rules, None, None, self.share_server)
2685 @ddt.data(True, False)
2686 def test_nfs_access_for_all_ip_addresses(self, is_allow):
2687 access_all = {
2688 'access_type': 'ip',
2689 'access_to': '0.0.0.0/0',
2690 'access_level': 'rw',
2691 }
2692 self.driver.plugin.helper.login()
2693 method = (self.driver.allow_access if is_allow
2694 else self.driver.deny_access)
2695 with mock.patch.object(self.driver.plugin.helper,
2696 '_get_access_from_share') as mock_call:
2697 mock_call.return_value = None
2699 method(self._context, self.share_nfs,
2700 access_all, self.share_server)
2702 mock_call.assert_called_with('1', '*', 'NFS')
2704 def test_get_share_client_type_fail(self):
2705 share_proto = 'fake_proto'
2706 self.assertRaises(exception.InvalidInput,
2707 self.driver.plugin.helper._get_share_client_type,
2708 share_proto)
2710 @ddt.data("NFS", "CIFS")
2711 def test_get_share_url_type(self, share_proto):
2712 share_url_type = self.driver.plugin.helper._get_share_url_type(
2713 share_proto)
2714 self.assertEqual(share_proto + 'HARE', share_url_type)
2716 def test_get_location_path_fail(self):
2717 share_name = 'share-fake-uuid'
2718 share_proto = 'fake_proto'
2719 self.assertRaises(exception.InvalidShareAccess,
2720 self.driver.plugin._get_location_path, share_name,
2721 share_proto)
2723 def test_allow_access_nfs_fail(self):
2724 self.driver.plugin.helper.login()
2725 self.assertRaises(exception.InvalidShareAccess,
2726 self.driver.allow_access, self._context,
2727 self.share_nfs, self.access_cert, self.share_server)
2729 def test_allow_access_cifs_fail(self):
2730 self.driver.plugin.helper.login()
2731 self.assertRaises(exception.InvalidShareAccess,
2732 self.driver.allow_access, self._context,
2733 self.share_cifs, self.access_ip, self.share_server)
2735 def test_deny_access_nfs_fail(self):
2736 self.driver.plugin.helper.login()
2737 result = self.driver.deny_access(self._context, self.share_nfs,
2738 self.access_cert, self.share_server)
2739 self.assertIsNone(result)
2741 def test_deny_access_not_exist_fail(self):
2742 self.driver.plugin.helper.login()
2743 access_ip_not_exist = {
2744 'access_type': 'ip',
2745 'access_to': '100.112.0.99',
2746 'access_level': 'rw',
2747 }
2748 result = self.driver.deny_access(self._context, self.share_nfs,
2749 access_ip_not_exist,
2750 self.share_server)
2751 self.assertIsNone(result)
2753 def test_deny_access_cifs_fail(self):
2754 self.driver.plugin.helper.login()
2755 result = self.driver.deny_access(self._context, self.share_cifs,
2756 self.access_ip, self.share_server)
2757 self.assertIsNone(result)
2759 def test_allow_access_ip_share_not_exist(self):
2760 self.driver.plugin.helper.login()
2761 self.driver.plugin.helper.share_exist = False
2762 self.assertRaises(exception.ShareResourceNotFound,
2763 self.driver.allow_access, self._context,
2764 self.share_nfs, self.access_ip, self.share_server)
2766 def test_deny_access_ip_share_not_exist(self):
2767 self.driver.plugin.helper.login()
2768 self.driver.plugin.helper.share_exist = False
2769 self.driver.deny_access(self._context, self.share_nfs,
2770 self.access_ip, self.share_server)
2772 def test_allow_access_ip_fail(self):
2773 self.driver.plugin.helper.login()
2774 self.driver.plugin.helper.test_normal = False
2775 self.assertRaises(exception.InvalidShare,
2776 self.driver.allow_access, self._context,
2777 self.share_nfs, self.access_ip, self.share_server)
2779 def test_allow_access_user_fail(self):
2780 self.driver.plugin.helper.login()
2781 self.driver.plugin.helper.test_normal = False
2782 self.assertRaises(exception.InvalidShare,
2783 self.driver.allow_access, self._context,
2784 self.share_cifs, self.access_user, self.share_server)
2786 def test_deny_access_ip_success(self):
2787 self.driver.plugin.helper.login()
2788 self.deny_flag = False
2789 self.driver.deny_access(self._context, self.share_nfs,
2790 self.access_ip_exist, self.share_server)
2791 self.assertTrue(self.driver.plugin.helper.deny_flag)
2793 def test_deny_access_user_success(self):
2794 self.driver.plugin.helper.login()
2795 self.deny_flag = False
2796 self.driver.deny_access(self._context, self.share_cifs,
2797 self.access_user_exist, self.share_server)
2798 self.assertTrue(self.driver.plugin.helper.deny_flag)
2800 def test_deny_access_ip_fail(self):
2801 self.driver.plugin.helper.login()
2802 self.driver.plugin.helper.test_normal = False
2803 self.assertRaises(exception.InvalidShare,
2804 self.driver.deny_access, self._context,
2805 self.share_nfs, self.access_ip, self.share_server)
2807 def test_deny_access_user_fail(self):
2808 self.driver.plugin.helper.login()
2809 self.driver.plugin.helper.test_normal = False
2810 self.assertRaises(exception.InvalidShare,
2811 self.driver.deny_access, self._context,
2812 self.share_cifs, self.access_user, self.share_server)
2814 def test_create_nfs_snapshot_success(self):
2815 self.driver.plugin.helper.login()
2816 self.driver.plugin.helper.create_snapflag = False
2817 self.driver.create_snapshot(self._context, self.nfs_snapshot,
2818 self.share_server)
2819 self.assertTrue(self.driver.plugin.helper.create_snapflag)
2821 def test_create_nfs_snapshot_share_not_exist(self):
2822 self.driver.plugin.helper.login()
2823 self.driver.plugin.helper.share_exist = False
2824 self.assertRaises(exception.InvalidInput,
2825 self.driver.create_snapshot, self._context,
2826 self.nfs_snapshot, self.share_server)
2828 def test_create_cifs_snapshot_success(self):
2829 self.driver.plugin.helper.login()
2830 self.driver.plugin.helper.create_snapflag = False
2831 self.driver.create_snapshot(self._context, self.cifs_snapshot,
2832 self.share_server)
2833 self.assertTrue(self.driver.plugin.helper.create_snapflag)
2835 def test_delete_snapshot_success(self):
2836 self.driver.plugin.helper.login()
2837 self.driver.plugin.helper.delete_flag = False
2838 self.driver.plugin.helper.snapshot_flag = True
2839 self.driver.delete_snapshot(self._context, self.nfs_snapshot,
2840 self.share_server)
2841 self.assertTrue(self.driver.plugin.helper.delete_flag)
2843 def test_delete_snapshot_not_exist_success(self):
2844 self.driver.plugin.helper.login()
2845 self.driver.plugin.helper.delete_flag = False
2846 self.driver.plugin.helper.snapshot_flag = False
2847 self.driver.delete_snapshot(self._context, self.nfs_snapshot,
2848 self.share_server)
2849 self.assertTrue(self.driver.plugin.helper.delete_flag)
2851 def test_create_nfs_snapshot_fail(self):
2852 self.driver.plugin.helper.login()
2853 self.driver.plugin.helper.test_normal = False
2854 self.assertRaises(exception.InvalidShare,
2855 self.driver.create_snapshot, self._context,
2856 self.nfs_snapshot, self.share_server)
2858 def test_create_cifs_snapshot_fail(self):
2859 self.driver.plugin.helper.login()
2860 self.driver.plugin.helper.test_normal = False
2861 self.assertRaises(exception.InvalidShare,
2862 self.driver.create_snapshot, self._context,
2863 self.cifs_snapshot, self.share_server)
2865 def test_delete_nfs_snapshot_fail(self):
2866 self.driver.plugin.helper.login()
2867 self.driver.plugin.helper.test_normal = False
2868 self.assertRaises(exception.InvalidShare,
2869 self.driver.delete_snapshot, self._context,
2870 self.nfs_snapshot, self.share_server)
2872 def test_delete_cifs_snapshot_fail(self):
2873 self.driver.plugin.helper.login()
2874 self.driver.plugin.helper.test_normal = False
2875 self.assertRaises(exception.InvalidShare,
2876 self.driver.delete_snapshot, self._context,
2877 self.cifs_snapshot, self.share_server)
2879 @ddt.data({"share_proto": "NFS",
2880 "path": ["100.115.10.68:/share_fake_manage_uuid"]},
2881 {"share_proto": "CIFS",
2882 "path": ["\\\\100.115.10.68\\share_fake_manage_uuid"]})
2883 @ddt.unpack
2884 def test_manage_share_nfs_success(self, share_proto, path):
2885 if share_proto == "NFS":
2886 share = self.share_manage_nfs
2887 elif share_proto == "CIFS": 2887 ↛ 2890line 2887 didn't jump to line 2890 because the condition on line 2887 was always true
2888 share = self.share_manage_cifs
2890 share_type = self.fake_type_w_extra['test_with_extra']
2891 self.mock_object(db, 'share_type_get',
2892 mock.Mock(return_value=share_type))
2893 self.driver.plugin.helper.login()
2894 share_info = self.driver.manage_existing(share,
2895 self.driver_options)
2896 self.assertEqual(4, share_info["size"])
2897 self.assertEqual(path, share_info["export_locations"])
2899 @ddt.data({"fs_alloctype": "THIN",
2900 "path": ["100.115.10.68:/share_fake_manage_uuid"]},
2901 {"fs_alloctype": "THICK",
2902 "path": ["100.115.10.68:/share_fake_uuid_thickfs"]})
2903 @ddt.unpack
2904 def test_manage_share_with_default_type(self, fs_alloctype, path):
2905 if fs_alloctype == "THIN":
2906 share = self.share_manage_nfs
2907 elif fs_alloctype == "THICK": 2907 ↛ 2910line 2907 didn't jump to line 2910 because the condition on line 2907 was always true
2908 share = self.share_nfs_thick_thickfs
2910 share_type = self.fake_type_not_extra['test_with_extra']
2911 self.mock_object(db, 'share_type_get',
2912 mock.Mock(return_value=share_type))
2913 self.driver.plugin.helper.login()
2914 share_info = self.driver.manage_existing(share,
2915 self.driver_options)
2916 self.assertEqual(4, share_info["size"])
2917 self.assertEqual(path, share_info["export_locations"])
2919 @ddt.data({"path": ["100.115.10.68:/share_fake_uuid_inpartition"]})
2920 @ddt.unpack
2921 def test_manage_share_remove_from_partition(self, path):
2922 share = self.share_nfs_inpartition
2924 share_type = self.fake_type_fake_extra['test_with_extra']
2925 self.mock_object(db,
2926 'share_type_get',
2927 mock.Mock(return_value=share_type))
2928 self.driver.plugin.helper.login()
2929 share_info = self.driver.manage_existing(share,
2930 self.driver_options)
2931 self.assertEqual(4, share_info["size"])
2932 self.assertEqual(path,
2933 share_info["export_locations"])
2935 @ddt.data({"flag": "share_not_exist", "exc": exception.InvalidShare},
2936 {"flag": "fs_status_error", "exc": exception.InvalidShare},
2937 {"flag": "poolname_not_match", "exc": exception.InvalidHost})
2938 @ddt.unpack
2939 def test_manage_share_fail(self, flag, exc):
2940 share = None
2941 if flag == "share_not_exist":
2942 self.driver.plugin.helper.share_exist = False
2943 share = self.share_nfs
2944 elif flag == "fs_status_error":
2945 self.driver.plugin.helper.fs_status_flag = False
2946 share = self.share_nfs
2947 elif flag == "poolname_not_match": 2947 ↛ 2950line 2947 didn't jump to line 2950 because the condition on line 2947 was always true
2948 share = self.share_pool_name_not_match
2950 self.driver.plugin.helper.login()
2951 share_type = self.fake_type_extra['test_with_extra']
2952 self.mock_object(db,
2953 'share_type_get',
2954 mock.Mock(return_value=share_type))
2955 self.assertRaises(exc,
2956 self.driver.manage_existing,
2957 share,
2958 self.driver_options)
2960 def test_manage_share_thickfs_set_dedupe_fail(self):
2961 share = self.share_nfs_thick_thickfs
2963 self.driver.plugin.helper.login()
2964 share_type = self.fake_type_thin_extra['test_with_extra']
2965 self.mock_object(db,
2966 'share_type_get',
2967 mock.Mock(return_value=share_type))
2969 self.assertRaises(exception.InvalidInput,
2970 self.driver.manage_existing,
2971 share,
2972 self.driver_options)
2974 def test_manage_share_thickfs_not_match_thinpool_fail(self):
2975 share = self.share_nfs_thickfs
2977 self.driver.plugin.helper.login()
2978 share_type = self.fake_type_extra['test_with_extra']
2979 self.mock_object(db,
2980 'share_type_get',
2981 mock.Mock(return_value=share_type))
2983 self.assertRaises(exception.InvalidHost,
2984 self.driver.manage_existing,
2985 share,
2986 self.driver_options)
2988 @ddt.data({"flag": "old_cache_id", "exc": exception.InvalidInput},
2989 {"flag": "not_old_cache_id", "exc": exception.InvalidInput})
2990 @ddt.unpack
2991 def test_manage_share_cache_not_exist(self, flag, exc):
2992 share = None
2993 if flag == "old_cache_id":
2994 share = self.share_nfs_inpartition
2995 elif flag == "not_old_cache_id": 2995 ↛ 2998line 2995 didn't jump to line 2998 because the condition on line 2995 was always true
2996 share = self.share_nfs
2998 self.driver.plugin.helper.cache_exist = False
2999 share_type = self.fake_type_w_extra['test_with_extra']
3000 self.mock_object(db,
3001 'share_type_get',
3002 mock.Mock(return_value=share_type))
3003 self.driver.plugin.helper.login()
3004 self.assertRaises(exc,
3005 self.driver.manage_existing,
3006 share,
3007 self.share_server)
3009 def test_manage_add_share_to_cache_fail(self):
3010 opts = dict(
3011 huawei_smartcache='true',
3012 huawei_smartpartition='true',
3013 cachename='test_cache_name_fake',
3014 partitionname='test_partition_name_fake',
3015 )
3016 fs = dict(
3017 SMARTCACHEID='6',
3018 SMARTPARTITIONID=None,
3019 )
3020 poolinfo = dict(
3021 type='Thin',
3022 )
3023 self.assertRaises(exception.InvalidInput,
3024 self.driver.plugin.check_retype_change_opts,
3025 opts, poolinfo, fs)
3027 def test_manage_notsetcache_fail(self):
3028 opts = dict(
3029 huawei_smartcache='true',
3030 huawei_smartpartition='true',
3031 cachename=None,
3032 partitionname='test_partition_name_fake',
3033 )
3034 fs = dict(
3035 SMARTCACHEID='6',
3036 SMARTPARTITIONID='6',
3037 )
3038 poolinfo = dict(
3039 type='Thin',
3040 )
3041 self.assertRaises(exception.InvalidInput,
3042 self.driver.plugin.check_retype_change_opts,
3043 opts, poolinfo, fs)
3045 @ddt.data({"flag": "old_partition_id", "exc": exception.InvalidInput},
3046 {"flag": "not_old_partition_id", "exc": exception.InvalidInput})
3047 @ddt.unpack
3048 def test_manage_share_partition_not_exist(self, flag, exc):
3049 share = None
3050 if flag == "old_partition_id":
3051 share = self.share_nfs_inpartition
3052 elif flag == "not_old_partition_id": 3052 ↛ 3055line 3052 didn't jump to line 3055 because the condition on line 3052 was always true
3053 share = self.share_nfs
3055 self.driver.plugin.helper.partition_exist = False
3056 share_type = self.fake_type_w_extra['test_with_extra']
3057 self.mock_object(db,
3058 'share_type_get',
3059 mock.Mock(return_value=share_type))
3060 self.driver.plugin.helper.login()
3061 self.assertRaises(exc,
3062 self.driver.manage_existing,
3063 share,
3064 self.share_server)
3066 def test_manage_add_share_to_partition_fail(self):
3067 opts = dict(
3068 huawei_smartcache='true',
3069 huawei_smartpartition='true',
3070 cachename='test_cache_name_fake',
3071 partitionname='test_partition_name_fake',
3072 )
3073 fs = dict(
3074 SMARTCACHEID=None,
3075 SMARTPARTITIONID='6',
3076 )
3077 poolinfo = dict(
3078 type='Thin',
3079 )
3080 self.assertRaises(exception.InvalidInput,
3081 self.driver.plugin.check_retype_change_opts,
3082 opts, poolinfo, fs)
3084 def test_manage_notset_partition_fail(self):
3085 opts = dict(
3086 huawei_smartcache='true',
3087 huawei_smartpartition='true',
3088 cachename='test_cache_name_fake',
3089 partitionname=None,
3090 )
3091 fs = dict(
3092 SMARTCACHEID=None,
3093 SMARTPARTITIONID='6',
3094 )
3095 poolinfo = dict(
3096 type='Thin',
3097 )
3098 self.assertRaises(exception.InvalidInput,
3099 self.driver.plugin.check_retype_change_opts,
3100 opts, poolinfo, fs)
3102 @ddt.data({"share_proto": "NFS",
3103 "export_path": "fake_ip:/share_fake_uuid"},
3104 {"share_proto": "NFS", "export_path": "fake_ip:/"},
3105 {"share_proto": "NFS",
3106 "export_path": "100.112.0.1://share_fake_uuid"},
3107 {"share_proto": "NFS", "export_path": None},
3108 {"share_proto": "NFS", "export_path": "\\share_fake_uuid"},
3109 {"share_proto": "CIFS",
3110 "export_path": "\\\\fake_ip\\share_fake_uuid"},
3111 {"share_proto": "CIFS",
3112 "export_path": "\\dd\\100.115.10.68\\share_fake_uuid"})
3113 @ddt.unpack
3114 def test_manage_export_path_fail(self, share_proto, export_path):
3115 share_manage_nfs_export_path_fail = {
3116 'id': 'fake_uuid',
3117 'project_id': 'fake_tenant_id',
3118 'display_name': 'fake',
3119 'name': 'share-fake-manage-uuid',
3120 'size': 1,
3121 'share_proto': share_proto,
3122 'share_network_id': 'fake_net_id',
3123 'share_server_id': 'fake-share-srv-id',
3124 'export_locations': [
3125 {'path': export_path},
3126 ],
3127 'host': 'fake_host@fake_backend#OpenStack_Pool',
3128 'share_type_id': 'fake_id'
3129 }
3130 share_type = self.fake_type_extra['test_with_extra']
3131 self.mock_object(db,
3132 'share_type_get',
3133 mock.Mock(return_value=share_type))
3134 self.driver.plugin.helper.login()
3135 self.assertRaises(exception.InvalidInput,
3136 self.driver.manage_existing,
3137 share_manage_nfs_export_path_fail,
3138 self.driver_options)
3140 def test_manage_logical_port_ip_fail(self):
3141 self.recreate_fake_conf_file(logical_port="")
3142 self.driver.plugin.configuration.manila_huawei_conf_file = (
3143 self.fake_conf_file)
3144 self.driver.plugin.helper.login()
3145 share_type = self.fake_type_extra['test_with_extra']
3146 self.mock_object(db,
3147 'share_type_get',
3148 mock.Mock(return_value=share_type))
3149 self.assertRaises(exception.InvalidInput,
3150 self.driver.manage_existing,
3151 self.share_nfs,
3152 self.driver_options)
3154 @ddt.data({"share_proto": "NFS",
3155 "provider_location": "share_snapshot_fake_snapshot_uuid"},
3156 {"share_proto": "CIFS",
3157 "provider_location": "share_snapshot_fake_snapshot_uuid"})
3158 @ddt.unpack
3159 def test_manage_existing_snapshot_success(self, share_proto,
3160 provider_location):
3161 if share_proto == "NFS":
3162 snapshot = self.storage_nfs_snapshot
3163 elif share_proto == "CIFS": 3163 ↛ 3165line 3163 didn't jump to line 3165 because the condition on line 3163 was always true
3164 snapshot = self.storage_cifs_snapshot
3165 self.driver.plugin.helper.login()
3166 snapshot_info = self.driver.manage_existing_snapshot(
3167 snapshot, self.driver_options)
3168 self.assertEqual(provider_location, snapshot_info['provider_location'])
3170 def test_manage_existing_snapshot_share_not_exist(self):
3171 self.driver.plugin.helper.login()
3172 self.mock_object(self.driver.plugin.helper,
3173 '_get_share_by_name',
3174 mock.Mock(return_value={}))
3175 self.assertRaises(exception.InvalidShare,
3176 self.driver.manage_existing_snapshot,
3177 self.storage_nfs_snapshot,
3178 self.driver_options)
3180 def test_manage_existing_snapshot_sharesnapshot_not_exist(self):
3181 self.driver.plugin.helper.login()
3182 self.mock_object(self.driver.plugin.helper,
3183 '_check_snapshot_id_exist',
3184 mock.Mock(return_value={}))
3185 self.assertRaises(exception.ManageInvalidShareSnapshot,
3186 self.driver.manage_existing_snapshot,
3187 self.storage_nfs_snapshot,
3188 self.driver_options)
3190 def test_manage_existing_snapshot_sharesnapshot_not_normal(self):
3191 snapshot_info = {"error": {"code": 0},
3192 "data": {"ID": "4@share_snapshot_fake_snapshot_uuid",
3193 "NAME": "share_snapshot_fake_snapshot_uuid",
3194 "HEALTHSTATUS": "2"}}
3195 self.driver.plugin.helper.login()
3196 self.mock_object(self.driver.plugin.helper,
3197 '_get_snapshot_by_id',
3198 mock.Mock(return_value=snapshot_info))
3199 self.assertRaises(exception.ManageInvalidShareSnapshot,
3200 self.driver.manage_existing_snapshot,
3201 self.storage_nfs_snapshot,
3202 self.driver_options)
3204 def test_get_pool_success(self):
3205 self.driver.plugin.helper.login()
3206 pool_name = self.driver.get_pool(self.share_nfs_host_not_exist)
3207 self.assertEqual('OpenStack_Pool', pool_name)
3209 def test_get_pool_fail(self):
3210 self.driver.plugin.helper.login()
3211 self.driver.plugin.helper.share_exist = False
3212 pool_name = self.driver.get_pool(self.share_nfs_host_not_exist)
3213 self.assertIsNone(pool_name)
3215 def test_multi_resturls_success(self):
3216 share_type = self.fake_type_not_extra['test_with_extra']
3217 self.mock_object(db,
3218 'share_type_get',
3219 mock.Mock(return_value=share_type))
3220 self.recreate_fake_conf_file(multi_url=True)
3221 self.driver.plugin.configuration.manila_huawei_conf_file = (
3222 self.fake_conf_file)
3223 self.driver.plugin.helper.test_multi_url_flag = 2
3224 location = self.driver.create_share(self._context, self.share_nfs,
3225 self.share_server)
3226 self.assertEqual("100.115.10.68:/share_fake_uuid", location)
3228 def test_multi_resturls_fail(self):
3229 self.recreate_fake_conf_file(multi_url=True)
3230 self.driver.plugin.configuration.manila_huawei_conf_file = (
3231 self.fake_conf_file)
3232 self.driver.plugin.helper.test_multi_url_flag = 1
3233 self.assertRaises(exception.InvalidShare,
3234 self.driver.create_share,
3235 self._context,
3236 self.share_nfs,
3237 self.share_server)
3239 @dec_driver_handles_share_servers
3240 def test_setup_server_success(self):
3241 backend_details = self.driver.setup_server(self.fake_network_info)
3242 fake_share_server = {
3243 'backend_details': backend_details
3244 }
3245 share_type = self.fake_type_not_extra['test_with_extra']
3246 self.mock_object(db,
3247 'share_type_get',
3248 mock.Mock(return_value=share_type))
3249 location = self.driver.create_share(self._context, self.share_nfs,
3250 fake_share_server)
3251 self.assertTrue(db.share_type_get.called)
3252 self.assertEqual((self.fake_network_allocations[0]['ip_address']
3253 + ":/share_fake_uuid"), location)
3255 @dec_driver_handles_share_servers
3256 def test_setup_server_with_bond_port_success(self):
3257 self.recreate_fake_conf_file(logical_port='fake_bond')
3258 self.driver.plugin.configuration.manila_huawei_conf_file = (
3259 self.fake_conf_file)
3260 backend_details = self.driver.setup_server(self.fake_network_info)
3261 fake_share_server = {
3262 'backend_details': backend_details
3263 }
3264 share_type = self.fake_type_not_extra['test_with_extra']
3265 self.mock_object(db,
3266 'share_type_get',
3267 mock.Mock(return_value=share_type))
3268 location = self.driver.create_share(self._context, self.share_nfs,
3269 fake_share_server)
3270 self.assertTrue(db.share_type_get.called)
3271 self.assertEqual((self.fake_network_allocations[0]['ip_address']
3272 + ":/share_fake_uuid"), location)
3274 @dec_driver_handles_share_servers
3275 def test_setup_server_logical_port_exist(self):
3276 def call_logical_port_exist(*args, **kwargs):
3277 url = args[0]
3278 method = args[2]
3279 if url == "/LIF" and method == "GET":
3280 data = """{"error":{"code":0},"data":[{
3281 "ID":"4",
3282 "HOMEPORTID":"4",
3283 "IPV4ADDR":"111.111.111.109",
3284 "IPV4MASK":"255.255.255.0",
3285 "OPERATIONALSTATUS":"false"}]}"""
3286 elif url == "/LIF/4" and method == "PUT":
3287 data = """{"error":{"code":0}}"""
3288 else:
3289 return self.driver.plugin.helper.do_call(*args, **kwargs)
3291 res_json = jsonutils.loads(data)
3292 return res_json
3294 self.mock_object(self.driver.plugin.helper, "create_logical_port")
3295 with mock.patch.object(self.driver.plugin.helper,
3296 'call') as mock_call:
3297 mock_call.side_effect = call_logical_port_exist
3298 backend_details = self.driver.setup_server(self.fake_network_info)
3299 self.assertEqual(backend_details['ip'],
3300 self.fake_network_allocations[0]['ip_address'])
3301 self.assertEqual(
3302 0, self.driver.plugin.helper.create_logical_port.call_count)
3304 @dec_driver_handles_share_servers
3305 def test_setup_server_vlan_exist(self):
3306 def call_vlan_exist(*args, **kwargs):
3307 url = args[0]
3308 method = args[2]
3309 if url == "/vlan" and method == "GET":
3310 data = """{"error":{"code":0},"data":[{
3311 "ID":"4",
3312 "NAME":"fake_vlan",
3313 "PORTID":"4",
3314 "TAG":"2"}]}"""
3315 else:
3316 return self.driver.plugin.helper.do_call(*args, **kwargs)
3318 res_json = jsonutils.loads(data)
3319 return res_json
3321 self.mock_object(self.driver.plugin.helper, "create_vlan")
3322 with mock.patch.object(self.driver.plugin.helper,
3323 'call') as mock_call:
3324 mock_call.side_effect = call_vlan_exist
3325 backend_details = self.driver.setup_server(self.fake_network_info)
3326 self.assertEqual(backend_details['ip'],
3327 self.fake_network_allocations[0]['ip_address'])
3328 self.assertEqual(
3329 0, self.driver.plugin.helper.create_vlan.call_count)
3331 def test_setup_server_invalid_ipv4(self):
3332 netwot_info_invali_ipv4 = self.fake_network_info
3333 netwot_info_invali_ipv4[0]['network_allocations'][0]['ip_address'] = (
3334 "::1/128")
3335 self.assertRaises(exception.InvalidInput,
3336 self.driver._setup_server,
3337 netwot_info_invali_ipv4)
3339 @dec_driver_handles_share_servers
3340 def test_setup_server_network_type_error(self):
3341 vxlan_netwotk_info = self.fake_network_info
3342 vxlan_netwotk_info[0]['network_type'] = 'vxlan'
3343 self.assertRaises(exception.NetworkBadConfigurationException,
3344 self.driver.setup_server,
3345 vxlan_netwotk_info)
3347 @dec_driver_handles_share_servers
3348 def test_setup_server_port_conf_miss(self):
3349 self.recreate_fake_conf_file(logical_port='')
3350 self.driver.plugin.configuration.manila_huawei_conf_file = (
3351 self.fake_conf_file)
3352 backend_details = self.driver.setup_server(self.fake_network_info)
3353 self.assertEqual(self.fake_network_allocations[0]['ip_address'],
3354 backend_details['ip'])
3356 @dec_driver_handles_share_servers
3357 def test_setup_server_port_offline_error(self):
3358 self.mock_object(self.driver.plugin,
3359 '_get_online_port',
3360 mock.Mock(return_value=(None, None)))
3361 self.assertRaises(exception.InvalidInput,
3362 self.driver.setup_server,
3363 self.fake_network_info)
3364 self.assertTrue(self.driver.plugin._get_online_port.called)
3366 @dec_driver_handles_share_servers
3367 def test_setup_server_port_not_exist(self):
3368 self.mock_object(self.driver.plugin.helper,
3369 'get_port_id',
3370 mock.Mock(return_value=None))
3371 self.assertRaises(exception.InvalidInput,
3372 self.driver.setup_server,
3373 self.fake_network_info)
3374 self.assertTrue(self.driver.plugin.helper.get_port_id.called)
3376 @dec_driver_handles_share_servers
3377 def test_setup_server_port_type_not_exist(self):
3378 self.mock_object(self.driver.plugin,
3379 '_get_optimal_port',
3380 mock.Mock(return_value=('CTE0.A.H2', '8')))
3381 self.assertRaises(exception.InvalidInput,
3382 self.driver.setup_server,
3383 self.fake_network_info)
3384 self.assertTrue(self.driver.plugin._get_optimal_port.called)
3386 @dec_driver_handles_share_servers
3387 def test_setup_server_choose_eth_port(self):
3388 self.recreate_fake_conf_file(logical_port='CTE0.A.H0;fake_bond')
3389 self.driver.plugin.configuration.manila_huawei_conf_file = (
3390 self.fake_conf_file)
3392 self.mock_object(self.driver.plugin.helper,
3393 'get_all_vlan',
3394 mock.Mock(return_value=[{'NAME': 'fake_bond.10'}]))
3395 fake_network_info = self.fake_network_info
3396 backend_details = self.driver.setup_server(fake_network_info)
3397 self.assertTrue(self.driver.plugin.helper.get_all_vlan.called)
3398 self.assertEqual(self.fake_network_allocations[0]['ip_address'],
3399 backend_details['ip'])
3401 @dec_driver_handles_share_servers
3402 def test_setup_server_choose_bond_port(self):
3403 self.recreate_fake_conf_file(logical_port='CTE0.A.H0;fake_bond')
3404 self.driver.plugin.configuration.manila_huawei_conf_file = (
3405 self.fake_conf_file)
3407 self.mock_object(self.driver.plugin.helper,
3408 'get_all_vlan',
3409 mock.Mock(return_value=[{'NAME': 'CTE0.A.H0.10'}]))
3410 fake_network_info = self.fake_network_info
3411 backend_details = self.driver.setup_server(fake_network_info)
3412 self.assertTrue(self.driver.plugin.helper.get_all_vlan.called)
3413 self.assertEqual(self.fake_network_allocations[0]['ip_address'],
3414 backend_details['ip'])
3416 @dec_driver_handles_share_servers
3417 def test_setup_server_choose_least_logic_port(self):
3418 self.recreate_fake_conf_file(
3419 logical_port='CTE0.A.H0;CTE0.A.H2;CTE0.B.H0;BOND0')
3420 self.driver.plugin.configuration.manila_huawei_conf_file = (
3421 self.fake_conf_file)
3422 fake_network_info = [{
3423 'server_id': '0',
3424 'segmentation_id': None,
3425 'cidr': '111.111.111.0/24',
3426 'network_allocations': self.fake_network_allocations,
3427 'network_type': None,
3428 }]
3429 self.mock_object(self.driver.plugin, '_get_online_port',
3430 mock.Mock(return_value=(['CTE0.A.H0', 'CTE0.A.H2',
3431 'CTE0.B.H0'], ['BOND0'])))
3432 self.mock_object(self.driver.plugin.helper, 'get_all_logical_port',
3433 mock.Mock(return_value=[
3434 {'HOMEPORTTYPE': constants.PORT_TYPE_ETH,
3435 'HOMEPORTNAME': 'CTE0.A.H0'},
3436 {'HOMEPORTTYPE': constants.PORT_TYPE_VLAN,
3437 'HOMEPORTNAME': 'CTE0.B.H0.10'},
3438 {'HOMEPORTTYPE': constants.PORT_TYPE_BOND,
3439 'HOMEPORTNAME': 'BOND0'}]))
3440 self.mock_object(self.driver.plugin.helper,
3441 'get_port_id',
3442 mock.Mock(return_value=4))
3444 backend_details = self.driver.setup_server(fake_network_info)
3446 self.assertEqual(self.fake_network_allocations[0]['ip_address'],
3447 backend_details['ip'])
3448 self.driver.plugin._get_online_port.assert_called_once_with(
3449 ['CTE0.A.H0', 'CTE0.A.H2', 'CTE0.B.H0', 'BOND0'])
3450 self.assertTrue(self.driver.plugin.helper.get_all_logical_port.called)
3451 self.driver.plugin.helper.get_port_id.assert_called_once_with(
3452 'CTE0.A.H2', constants.PORT_TYPE_ETH)
3454 @dec_driver_handles_share_servers
3455 def test_setup_server_create_vlan_fail(self):
3456 def call_create_vlan_fail(*args, **kwargs):
3457 url = args[0]
3458 method = args[2]
3459 if url == "/vlan" and method == "POST":
3460 data = """{"error":{"code":1}}"""
3461 res_json = jsonutils.loads(data)
3462 return res_json
3463 else:
3464 return self.driver.plugin.helper.do_call(*args, **kwargs)
3466 with mock.patch.object(self.driver.plugin.helper,
3467 'call') as mock_call:
3468 mock_call.side_effect = call_create_vlan_fail
3469 self.assertRaises(exception.InvalidShare,
3470 self.driver.setup_server,
3471 self.fake_network_info)
3473 @dec_driver_handles_share_servers
3474 def test_setup_server_create_logical_port_fail(self):
3475 def call_create_logical_port_fail(*args, **kwargs):
3476 url = args[0]
3477 method = args[2]
3478 if url == "/LIF" and method == "POST":
3479 data = """{"error":{"code":1}}"""
3480 res_json = jsonutils.loads(data)
3481 return res_json
3482 else:
3483 return self.driver.plugin.helper.do_call(*args, **kwargs)
3485 fake_network_info = self.fake_network_info
3486 fake_network_info[0]['security_services'] = [
3487 self.fake_active_directory, self.fake_ldap]
3488 self.mock_object(self.driver.plugin.helper, "delete_vlan")
3489 self.mock_object(self.driver.plugin.helper, "delete_AD_config")
3490 self.mock_object(self.driver.plugin.helper, "delete_LDAP_config")
3491 self.mock_object(self.driver.plugin.helper,
3492 "get_AD_config",
3493 mock.Mock(side_effect=[None,
3494 {'DOMAINSTATUS': '1'},
3495 {'DOMAINSTATUS': '0'}]))
3496 self.mock_object(
3497 self.driver.plugin.helper,
3498 "get_LDAP_config",
3499 mock.Mock(
3500 side_effect=[None, {'BASEDN': 'dc=huawei,dc=com'}]))
3501 with mock.patch.object(self.driver.plugin.helper,
3502 'call') as mock_call:
3503 mock_call.side_effect = call_create_logical_port_fail
3504 self.assertRaises(exception.InvalidShare,
3505 self.driver.setup_server,
3506 fake_network_info)
3507 self.assertTrue(self.driver.plugin.helper.get_AD_config.called)
3508 self.assertTrue(self.driver.plugin.helper.get_LDAP_config.called)
3509 self.assertEqual(
3510 1, self.driver.plugin.helper.delete_vlan.call_count)
3511 self.assertEqual(
3512 1, self.driver.plugin.helper.delete_AD_config.call_count)
3513 self.assertEqual(
3514 1, self.driver.plugin.helper.delete_LDAP_config.call_count)
3516 @dec_driver_handles_share_servers
3517 def test_setup_server_with_ad_domain_success(self):
3518 fake_network_info = self.fake_network_info
3519 fake_network_info[0]['security_services'] = (
3520 [self.fake_active_directory])
3521 self.mock_object(self.driver.plugin.helper,
3522 "get_AD_config",
3523 mock.Mock(
3524 side_effect=[None,
3525 {'DOMAINSTATUS': '0',
3526 'FULLDOMAINNAME': 'huawei.com'},
3527 {'DOMAINSTATUS': '1',
3528 'FULLDOMAINNAME': 'huawei.com'}]))
3529 backend_details = self.driver.setup_server(fake_network_info)
3530 self.assertEqual(self.fake_network_allocations[0]['ip_address'],
3531 backend_details['ip'])
3532 self.assertTrue(self.driver.plugin.helper.get_AD_config.called)
3534 @ddt.data(
3535 "100.97.5.87",
3536 "100.97.5.87,100.97.5.88",
3537 "100.97.5.87,100.97.5.88,100.97.5.89"
3538 )
3539 @dec_driver_handles_share_servers
3540 def test_setup_server_with_ldap_domain_success(self, server_ips):
3541 fake_network_info = self.fake_network_info
3542 fake_network_info[0]['security_services'] = [self.fake_ldap]
3543 fake_network_info[0]['security_services'][0]['server'] = server_ips
3544 self.mock_object(
3545 self.driver.plugin.helper,
3546 "get_LDAP_config",
3547 mock.Mock(
3548 side_effect=[None, {'BASEDN': 'dc=huawei,dc=com'}]))
3549 backend_details = self.driver.setup_server(fake_network_info)
3550 self.assertEqual(self.fake_network_allocations[0]['ip_address'],
3551 backend_details['ip'])
3552 self.assertTrue(self.driver.plugin.helper.get_LDAP_config.called)
3554 @dec_driver_handles_share_servers
3555 def test_setup_server_with_ldap_domain_fail(self):
3556 server_ips = "100.97.5.87,100.97.5.88,100.97.5.89,100.97.5.86"
3557 fake_network_info = self.fake_network_info
3558 fake_network_info[0]['security_services'] = [self.fake_ldap]
3559 fake_network_info[0]['security_services'][0]['server'] = server_ips
3560 self.mock_object(
3561 self.driver.plugin.helper,
3562 "get_LDAP_config",
3563 mock.Mock(
3564 side_effect=[None, {'BASEDN': 'dc=huawei,dc=com'}]))
3565 self.assertRaises(exception.InvalidInput,
3566 self.driver.setup_server,
3567 fake_network_info)
3568 self.assertTrue(self.driver.plugin.helper.get_LDAP_config.called)
3570 @ddt.data(
3571 {'type': 'fake_unsupport'},
3572 {'type': 'active_directory',
3573 'dns_ip': '',
3574 'user': '',
3575 'password': '',
3576 'domain': ''},
3577 {'type': 'ldap',
3578 'server': '',
3579 'domain': ''},
3580 )
3581 @dec_driver_handles_share_servers
3582 def test_setup_server_with_security_service_invalid(self, data):
3583 fake_network_info = self.fake_network_info
3584 fake_network_info[0]['security_services'] = [data]
3585 self.assertRaises(exception.InvalidInput,
3586 self.driver.setup_server,
3587 fake_network_info)
3589 @dec_driver_handles_share_servers
3590 def test_setup_server_with_security_service_number_invalid(self):
3591 fake_network_info = self.fake_network_info
3592 ss = [
3593 {'type': 'fake_unsupport'},
3594 {'type': 'active_directory',
3595 'dns_ip': '',
3596 'user': '',
3597 'password': '',
3598 'domain': ''},
3599 {'type': 'ldap',
3600 'server': '',
3601 'domain': ''},
3602 ]
3603 fake_network_info[0]['security_services'] = ss
3604 self.assertRaises(exception.InvalidInput,
3605 self.driver.setup_server,
3606 fake_network_info)
3608 @dec_driver_handles_share_servers
3609 def test_setup_server_dns_exist_error(self):
3610 fake_network_info = self.fake_network_info
3611 fake_network_info[0]['security_services'] = (
3612 [self.fake_active_directory])
3613 self.mock_object(self.driver.plugin.helper,
3614 "get_DNS_ip_address",
3615 mock.Mock(return_value=['100.97.5.85']))
3616 self.assertRaises(exception.InvalidInput,
3617 self.driver.setup_server,
3618 fake_network_info)
3619 self.assertTrue(self.driver.plugin.helper.get_DNS_ip_address.called)
3621 @dec_driver_handles_share_servers
3622 def test_setup_server_ad_exist_error(self):
3623 fake_network_info = self.fake_network_info
3624 fake_network_info[0]['security_services'] = (
3625 [self.fake_active_directory])
3626 self.mock_object(self.driver.plugin.helper,
3627 "get_AD_config",
3628 mock.Mock(
3629 return_value={'DOMAINSTATUS': '1',
3630 'FULLDOMAINNAME': 'huawei.com'}))
3631 self.assertRaises(exception.InvalidInput,
3632 self.driver.setup_server,
3633 fake_network_info)
3634 self.assertTrue(self.driver.plugin.helper.get_AD_config.called)
3636 @dec_driver_handles_share_servers
3637 def test_setup_server_ldap_exist_error(self):
3638 fake_network_info = self.fake_network_info
3639 fake_network_info[0]['security_services'] = [self.fake_ldap]
3640 self.mock_object(self.driver.plugin.helper,
3641 "get_LDAP_config",
3642 mock.Mock(
3643 return_value={'LDAPSERVER': '100.97.5.87'}))
3644 self.assertRaises(exception.InvalidInput,
3645 self.driver.setup_server,
3646 fake_network_info)
3647 self.assertTrue(self.driver.plugin.helper.get_LDAP_config.called)
3649 @dec_driver_handles_share_servers
3650 def test_setup_server_with_dns_fail(self):
3651 fake_network_info = self.fake_network_info
3652 fake_active_directory = self.fake_active_directory
3653 ip_list = "100.97.5.5,100.97.5.6,100.97.5.7,100.97.5.8"
3654 fake_active_directory['dns_ip'] = ip_list
3655 fake_network_info[0]['security_services'] = [fake_active_directory]
3656 self.mock_object(
3657 self.driver.plugin.helper,
3658 "get_AD_config",
3659 mock.Mock(side_effect=[None, {'DOMAINSTATUS': '1'}]))
3660 self.assertRaises(exception.InvalidInput,
3661 self.driver.setup_server,
3662 fake_network_info)
3663 self.assertTrue(self.driver.plugin.helper.get_AD_config.called)
3665 @dec_driver_handles_share_servers
3666 def test_setup_server_with_ad_domain_fail(self):
3667 fake_network_info = self.fake_network_info
3668 fake_network_info[0]['security_services'] = (
3669 [self.fake_active_directory])
3670 self.mock_object(self.driver.plugin,
3671 '_get_wait_interval',
3672 mock.Mock(return_value=1))
3673 self.mock_object(self.driver.plugin,
3674 '_get_timeout',
3675 mock.Mock(return_value=1))
3676 self.mock_object(
3677 self.driver.plugin.helper,
3678 "get_AD_config",
3679 mock.Mock(side_effect=[None,
3680 {'DOMAINSTATUS': '0',
3681 'FULLDOMAINNAME': 'huawei.com'}]))
3682 self.mock_object(self.driver.plugin.helper, "set_DNS_ip_address")
3683 self.assertRaises(exception.InvalidShare,
3684 self.driver.setup_server,
3685 fake_network_info)
3686 self.assertTrue(self.driver.plugin.helper.get_AD_config.called)
3687 self.assertTrue(self.driver.plugin._get_wait_interval.called)
3688 self.assertTrue(self.driver.plugin._get_timeout.called)
3689 self.assertEqual(
3690 2, self.driver.plugin.helper.set_DNS_ip_address.call_count)
3692 def test_teardown_server_success(self):
3693 server_details = {
3694 "logical_port_id": "1",
3695 "vlan_id": "2",
3696 "ad_created": "1",
3697 "ldap_created": "1",
3698 }
3699 security_services = [
3700 self.fake_ldap,
3701 self.fake_active_directory
3702 ]
3703 self.logical_port_deleted = False
3704 self.vlan_deleted = False
3705 self.ad_deleted = False
3706 self.ldap_deleted = False
3707 self.dns_deleted = False
3709 def fake_teardown_call(*args, **kwargs):
3710 url = args[0]
3711 method = args[2]
3712 if url.startswith("/LIF"):
3713 if method == "GET":
3714 data = """{"error":{"code":0},"data":[{
3715 "ID":"1"}]}"""
3716 elif method == "DELETE": 3716 ↛ 3765line 3716 didn't jump to line 3765 because the condition on line 3716 was always true
3717 data = """{"error":{"code":0}}"""
3718 self.logical_port_deleted = True
3719 elif url.startswith("/vlan"):
3720 if method == "GET":
3721 data = """{"error":{"code":0},"data":[{
3722 "ID":"2"}]}"""
3723 elif method == "DELETE": 3723 ↛ 3765line 3723 didn't jump to line 3765 because the condition on line 3723 was always true
3724 data = """{"error":{"code":1073813505}}"""
3725 self.vlan_deleted = True
3726 elif url == "/AD_CONFIG":
3727 if method == "PUT":
3728 data = """{"error":{"code":0}}"""
3729 self.ad_deleted = True
3730 elif method == "GET": 3730 ↛ 3739line 3730 didn't jump to line 3739 because the condition on line 3730 was always true
3731 if self.ad_deleted:
3732 data = """{"error":{"code":0},"data":{
3733 "DOMAINSTATUS":"0"}}"""
3734 else:
3735 data = """{"error":{"code":0},"data":{
3736 "DOMAINSTATUS":"1",
3737 "FULLDOMAINNAME":"huawei.com"}}"""
3738 else:
3739 data = """{"error":{"code":0}}"""
3740 elif url == "/LDAP_CONFIG":
3741 if method == "DELETE":
3742 data = """{"error":{"code":0}}"""
3743 self.ldap_deleted = True
3744 elif method == "GET": 3744 ↛ 3752line 3744 didn't jump to line 3752 because the condition on line 3744 was always true
3745 if self.ldap_deleted: 3745 ↛ 3746line 3745 didn't jump to line 3746 because the condition on line 3745 was never true
3746 data = """{"error":{"code":0}}"""
3747 else:
3748 data = """{"error":{"code":0},"data":{
3749 "LDAPSERVER":"100.97.5.87",
3750 "BASEDN":"dc=huawei,dc=com"}}"""
3751 else:
3752 data = """{"error":{"code":0}}"""
3753 elif url == "/DNS_Server": 3753 ↛ 3763line 3753 didn't jump to line 3763 because the condition on line 3753 was always true
3754 if method == "GET":
3755 data = "{\"error\":{\"code\":0},\"data\":{\
3756 \"ADDRESS\":\"[\\\"100.97.5.5\\\",\\\"\\\"]\"}}"
3757 elif method == "PUT": 3757 ↛ 3761line 3757 didn't jump to line 3761 because the condition on line 3757 was always true
3758 data = """{"error":{"code":0}}"""
3759 self.dns_deleted = True
3760 else:
3761 data = """{"error":{"code":0}}"""
3762 else:
3763 return self.driver.plugin.helper.do_call(*args, **kwargs)
3765 res_json = jsonutils.loads(data)
3766 return res_json
3768 with mock.patch.object(self.driver.plugin.helper,
3769 'call') as mock_call:
3770 mock_call.side_effect = fake_teardown_call
3771 self.driver._teardown_server(server_details, security_services)
3772 self.assertTrue(self.logical_port_deleted)
3773 self.assertTrue(self.vlan_deleted)
3774 self.assertTrue(self.ad_deleted)
3775 self.assertTrue(self.ldap_deleted)
3776 self.assertTrue(self.dns_deleted)
3778 def test_teardown_server_with_already_deleted(self):
3779 server_details = {
3780 "logical_port_id": "1",
3781 "vlan_id": "2",
3782 "ad_created": "1",
3783 "ldap_created": "1",
3784 }
3785 security_services = [
3786 self.fake_ldap,
3787 self.fake_active_directory
3788 ]
3790 self.mock_object(self.driver.plugin.helper,
3791 "check_logical_port_exists_by_id",
3792 mock.Mock(return_value=False))
3793 self.mock_object(self.driver.plugin.helper,
3794 "check_vlan_exists_by_id",
3795 mock.Mock(return_value=False))
3796 self.mock_object(self.driver.plugin.helper,
3797 "get_DNS_ip_address",
3798 mock.Mock(return_value=None))
3799 self.mock_object(self.driver.plugin.helper,
3800 "get_AD_domain_name",
3801 mock.Mock(return_value=(False, None)))
3802 self.mock_object(self.driver.plugin.helper,
3803 "get_LDAP_domain_server",
3804 mock.Mock(return_value=(False, None)))
3806 self.driver._teardown_server(server_details, security_services)
3807 self.assertEqual(1, (self.driver.plugin.helper.
3808 check_logical_port_exists_by_id.call_count))
3809 self.assertEqual(1, (self.driver.plugin.helper.
3810 check_vlan_exists_by_id.call_count))
3811 self.assertEqual(1, (self.driver.plugin.helper.
3812 get_DNS_ip_address.call_count))
3813 self.assertEqual(1, (self.driver.plugin.helper.
3814 get_AD_domain_name.call_count))
3815 self.assertEqual(1, (self.driver.plugin.helper.
3816 get_LDAP_domain_server.call_count))
3818 def test_teardown_server_with_vlan_logical_port_deleted(self):
3819 server_details = {
3820 "logical_port_id": "1",
3821 "vlan_id": "2",
3822 }
3824 self.mock_object(self.driver.plugin.helper,
3825 'get_all_logical_port',
3826 mock.Mock(return_value=[{'ID': '4'}]))
3827 self.mock_object(self.driver.plugin.helper,
3828 'get_all_vlan',
3829 mock.Mock(return_value=[{'ID': '4'}]))
3830 self.driver._teardown_server(server_details, None)
3831 self.assertEqual(1, (self.driver.plugin.helper.
3832 get_all_logical_port.call_count))
3833 self.assertEqual(1, (self.driver.plugin.helper.
3834 get_all_vlan.call_count))
3836 def test_teardown_server_with_empty_detail(self):
3837 server_details = {}
3838 with mock.patch.object(connection.LOG, 'debug') as mock_debug:
3839 self.driver._teardown_server(server_details, None)
3840 mock_debug.assert_called_with('Server details are empty.')
3842 @ddt.data({"share_proto": "NFS",
3843 "path": ["100.115.10.68:/share_fake_uuid"]},
3844 {"share_proto": "CIFS",
3845 "path": ["\\\\100.115.10.68\\share_fake_uuid"]})
3846 @ddt.unpack
3847 def test_ensure_share_sucess(self, share_proto, path):
3848 share = self._get_share_by_proto(share_proto)
3850 self.driver.plugin.helper.login()
3851 location = self.driver.ensure_share(self._context,
3852 share,
3853 self.share_server)
3854 self.assertEqual(path, location)
3856 @ddt.data({"share_proto": "NFS",
3857 "path": ["111.111.111.109:/share_fake_uuid"]},
3858 {"share_proto": "CIFS",
3859 "path": ["\\\\111.111.111.109\\share_fake_uuid"]})
3860 @ddt.unpack
3861 @dec_driver_handles_share_servers
3862 def test_ensure_share_with_share_server_sucess(self, share_proto, path):
3863 share = self._get_share_by_proto(share_proto)
3864 backend_details = self.driver.setup_server(self.fake_network_info)
3865 fake_share_server = {'backend_details': backend_details}
3867 location = self.driver.ensure_share(self._context,
3868 share,
3869 fake_share_server)
3870 self.assertEqual(path, location)
3872 @ddt.data({"share_proto": "NFS"},
3873 {"share_proto": "CIFS"})
3874 @ddt.unpack
3875 def test_ensure_share_get_share_fail(self, share_proto):
3876 share = self._get_share_by_proto(share_proto)
3877 self.mock_object(self.driver.plugin.helper,
3878 '_get_share_by_name',
3879 mock.Mock(return_value={}))
3881 self.driver.plugin.helper.login()
3882 self.assertRaises(exception.ShareResourceNotFound,
3883 self.driver.ensure_share,
3884 self._context,
3885 share,
3886 self.share_server)
3888 def test_ensure_share_get_filesystem_status_fail(self):
3889 self.driver.plugin.helper.fs_status_flag = False
3890 share = self.share_nfs_thickfs
3892 self.driver.plugin.helper.login()
3893 self.assertRaises(exception.StorageResourceException,
3894 self.driver.ensure_share,
3895 self._context,
3896 share,
3897 self.share_server)
3899 def _add_conf_file_element(self, doc, parent_element, name, value=None):
3900 new_element = doc.createElement(name)
3901 if value: 3901 ↛ 3904line 3901 didn't jump to line 3904 because the condition on line 3901 was always true
3902 new_text = doc.createTextNode(value)
3903 new_element.appendChild(new_text)
3904 parent_element.appendChild(new_element)
3906 def create_fake_conf_file(self, fake_conf_file,
3907 product_flag=True, username_flag=True,
3908 pool_node_flag=True, timeout_flag=True,
3909 wait_interval_flag=True,
3910 sectorsize_value='4',
3911 multi_url=False,
3912 logical_port='100.115.10.68',
3913 snapshot_support=True,
3914 replication_support=False):
3915 doc = xml.dom.minidom.Document()
3916 config = doc.createElement('Config')
3917 doc.appendChild(config)
3919 storage = doc.createElement('Storage')
3920 config.appendChild(storage)
3922 if self.configuration.driver_handles_share_servers:
3923 port0 = doc.createElement('Port')
3924 port0_text = doc.createTextNode(logical_port)
3925 port0.appendChild(port0_text)
3926 storage.appendChild(port0)
3927 else:
3928 controllerip0 = doc.createElement('LogicalPortIP')
3929 controllerip0_text = doc.createTextNode(logical_port)
3930 controllerip0.appendChild(controllerip0_text)
3931 storage.appendChild(controllerip0)
3933 if product_flag:
3934 product_text = doc.createTextNode('V3')
3935 else:
3936 product_text = doc.createTextNode('V3_fail')
3938 product = doc.createElement('Product')
3939 product.appendChild(product_text)
3940 storage.appendChild(product)
3942 if username_flag:
3943 username_text = doc.createTextNode('admin')
3944 else:
3945 username_text = doc.createTextNode('')
3947 username = doc.createElement('UserName')
3948 username.appendChild(username_text)
3949 storage.appendChild(username)
3951 userpassword = doc.createElement('UserPassword')
3952 userpassword_text = doc.createTextNode('Admin@storage')
3953 userpassword.appendChild(userpassword_text)
3954 storage.appendChild(userpassword)
3955 url = doc.createElement('RestURL')
3956 if multi_url:
3957 url_text = doc.createTextNode('http://100.115.10.69:8082/'
3958 'deviceManager/rest/;'
3959 'http://100.115.10.70:8082/'
3960 'deviceManager/rest/')
3961 else:
3962 url_text = doc.createTextNode('http://100.115.10.69:8082/'
3963 'deviceManager/rest/')
3964 url.appendChild(url_text)
3965 storage.appendChild(url)
3967 if snapshot_support:
3968 self._add_conf_file_element(
3969 doc, storage, 'SnapshotSupport', 'True')
3971 if replication_support:
3972 self._add_conf_file_element(
3973 doc, storage, 'ReplicationSupport', 'True')
3975 lun = doc.createElement('Filesystem')
3976 config.appendChild(lun)
3978 storagepool = doc.createElement('StoragePool')
3979 if pool_node_flag:
3980 pool_text = doc.createTextNode('OpenStack_Pool;OpenStack_Pool2; ;')
3981 else:
3982 pool_text = doc.createTextNode('')
3983 storagepool.appendChild(pool_text)
3985 timeout = doc.createElement('Timeout')
3987 if timeout_flag:
3988 timeout_text = doc.createTextNode('60')
3989 else:
3990 timeout_text = doc.createTextNode('')
3991 timeout.appendChild(timeout_text)
3993 waitinterval = doc.createElement('WaitInterval')
3994 if wait_interval_flag:
3995 waitinterval_text = doc.createTextNode('3')
3996 else:
3997 waitinterval_text = doc.createTextNode('')
3998 waitinterval.appendChild(waitinterval_text)
4000 NFSClient = doc.createElement('NFSClient')
4002 virtualip = doc.createElement('IP')
4003 virtualip_text = doc.createTextNode('100.112.0.1')
4004 virtualip.appendChild(virtualip_text)
4005 NFSClient.appendChild(virtualip)
4006 CIFSClient = doc.createElement('CIFSClient')
4008 username = doc.createElement('UserName')
4009 username_text = doc.createTextNode('user_name')
4010 username.appendChild(username_text)
4011 CIFSClient.appendChild(username)
4013 userpassword = doc.createElement('UserPassword')
4014 userpassword_text = doc.createTextNode('user_password')
4015 userpassword.appendChild(userpassword_text)
4016 CIFSClient.appendChild(userpassword)
4018 lun.appendChild(NFSClient)
4019 lun.appendChild(CIFSClient)
4020 lun.appendChild(timeout)
4021 lun.appendChild(waitinterval)
4022 lun.appendChild(storagepool)
4024 if sectorsize_value:
4025 sectorsize = doc.createElement('SectorSize')
4026 sectorsize_text = doc.createTextNode(sectorsize_value)
4027 sectorsize.appendChild(sectorsize_text)
4028 lun.appendChild(sectorsize)
4030 prefetch = doc.createElement('Prefetch')
4031 prefetch.setAttribute('Type', '0')
4032 prefetch.setAttribute('Value', '0')
4033 lun.appendChild(prefetch)
4035 fakefile = open(fake_conf_file, 'w')
4036 fakefile.write(doc.toprettyxml(indent=''))
4037 fakefile.close()
4039 def recreate_fake_conf_file(self, product_flag=True, username_flag=True,
4040 pool_node_flag=True, timeout_flag=True,
4041 wait_interval_flag=True,
4042 sectorsize_value='4',
4043 multi_url=False,
4044 logical_port='100.115.10.68',
4045 snapshot_support=True,
4046 replication_support=False):
4047 self.tmp_dir = tempfile.mkdtemp()
4048 self.fake_conf_file = self.tmp_dir + '/manila_huawei_conf.xml'
4049 self.addCleanup(shutil.rmtree, self.tmp_dir)
4050 self.create_fake_conf_file(self.fake_conf_file, product_flag,
4051 username_flag, pool_node_flag,
4052 timeout_flag, wait_interval_flag,
4053 sectorsize_value,
4054 multi_url, logical_port,
4055 snapshot_support, replication_support)
4056 self.addCleanup(os.remove, self.fake_conf_file)
4058 @ddt.data(common_constants.STATUS_ERROR,
4059 common_constants.REPLICA_STATE_IN_SYNC,
4060 common_constants.REPLICA_STATE_OUT_OF_SYNC)
4061 def test_create_replica_success(self, replica_state):
4062 share_type = self.fake_type_not_extra['test_with_extra']
4063 self.mock_object(db, 'share_type_get',
4064 mock.Mock(return_value=share_type))
4066 if replica_state == common_constants.STATUS_ERROR:
4067 self.driver.plugin.helper.custom_results[
4068 '/REPLICATIONPAIR/fake_pair_id'] = {
4069 "GET": """{"error":{"code":0},
4070 "data":{"HEALTHSTATUS": "2"}}"""}
4071 elif replica_state == common_constants.REPLICA_STATE_OUT_OF_SYNC:
4072 self.driver.plugin.helper.custom_results[
4073 '/REPLICATIONPAIR/fake_pair_id'] = {
4074 "GET": """{"error":{"code":0},
4075 "data":{"HEALTHSTATUS": "1",
4076 "RUNNINGSTATUS": "1",
4077 "SECRESDATASTATUS": "5"}}"""}
4079 result = self.driver.create_replica(
4080 self._context,
4081 [self.active_replica, self.new_replica],
4082 self.new_replica,
4083 [], [], None)
4085 expected = {
4086 'export_locations': ['100.115.10.68:/share_fake_new_uuid'],
4087 'replica_state': replica_state,
4088 'access_rules_status': common_constants.STATUS_ACTIVE,
4089 }
4091 self.assertEqual(expected, result)
4092 self.assertEqual('fake_pair_id',
4093 self.driver.plugin.private_storage.get(
4094 'fake_share_id', 'replica_pair_id'))
4096 @ddt.data({'url': '/FILESYSTEM?filter=NAME::share_fake_uuid'
4097 '&range=[0-8191]',
4098 'url_result': '{"error":{"code":0}}',
4099 'expected_exception': exception.ReplicationException},
4100 {'url': '/NFSHARE',
4101 'url_result': '{"error":{"code":-403}}',
4102 'expected_exception': exception.InvalidShare},
4103 {'url': '/REPLICATIONPAIR',
4104 'url_result': '{"error":{"code":-403}}',
4105 'expected_exception': exception.InvalidShare},)
4106 @ddt.unpack
4107 def test_create_replica_fail(self, url, url_result, expected_exception):
4108 share_type = self.fake_type_not_extra['test_with_extra']
4109 self.mock_object(db, 'share_type_get',
4110 mock.Mock(return_value=share_type))
4112 self.driver.plugin.helper.custom_results[url] = url_result
4114 self.assertRaises(expected_exception,
4115 self.driver.create_replica,
4116 self._context,
4117 [self.active_replica, self.new_replica],
4118 self.new_replica,
4119 [], [], None)
4120 self.assertIsNone(self.driver.plugin.private_storage.get(
4121 'fake_share_id', 'replica_pair_id'))
4123 def test_create_replica_with_get_state_fail(self):
4124 share_type = self.fake_type_not_extra['test_with_extra']
4125 self.mock_object(db, 'share_type_get',
4126 mock.Mock(return_value=share_type))
4128 self.driver.plugin.helper.custom_results[
4129 '/REPLICATIONPAIR/fake_pair_id'] = {
4130 "GET": """{"error":{"code":-403}}"""}
4132 result = self.driver.create_replica(
4133 self._context,
4134 [self.active_replica, self.new_replica],
4135 self.new_replica,
4136 [], [], None)
4138 expected = {
4139 'export_locations': ['100.115.10.68:/share_fake_new_uuid'],
4140 'replica_state': common_constants.STATUS_ERROR,
4141 'access_rules_status': common_constants.STATUS_ACTIVE,
4142 }
4144 self.assertEqual(expected, result)
4145 self.assertEqual('fake_pair_id',
4146 self.driver.plugin.private_storage.get(
4147 'fake_share_id', 'replica_pair_id'))
4149 def test_create_replica_with_already_exists(self):
4150 self.driver.plugin.private_storage.update(
4151 'fake_share_id',
4152 {'replica_pair_id': 'fake_pair_id'})
4154 self.assertRaises(exception.ReplicationException,
4155 self.driver.create_replica,
4156 self._context,
4157 [self.active_replica, self.new_replica],
4158 self.new_replica,
4159 [], [], None)
4161 @ddt.data({'pair_info': """{"HEALTHSTATUS": "2",
4162 "SECRESDATASTATUS": "2",
4163 "ISPRIMARY": "false",
4164 "SECRESACCESS": "1",
4165 "RUNNINGSTATUS": "1"}""",
4166 'assert_method': 'get_replication_pair_by_id'},
4167 {'pair_info': """{"HEALTHSTATUS": "1",
4168 "SECRESDATASTATUS": "2",
4169 "ISPRIMARY": "true",
4170 "SECRESACCESS": "1",
4171 "RUNNINGSTATUS": "1"}""",
4172 'assert_method': 'switch_replication_pair'},
4173 {'pair_info': """{"HEALTHSTATUS": "1",
4174 "SECRESDATASTATUS": "2",
4175 "ISPRIMARY": "false",
4176 "SECRESACCESS": "3",
4177 "RUNNINGSTATUS": "1"}""",
4178 'assert_method': 'set_pair_secondary_write_lock'},
4179 {'pair_info': """{"HEALTHSTATUS": "1",
4180 "SECRESDATASTATUS": "2",
4181 "ISPRIMARY": "false",
4182 "SECRESACCESS": "1",
4183 "RUNNINGSTATUS": "33"}""",
4184 'assert_method': 'sync_replication_pair'},)
4185 @ddt.unpack
4186 def test_update_replica_state_success(self, pair_info, assert_method):
4187 self.driver.plugin.private_storage.update(
4188 'fake_share_id',
4189 {'replica_pair_id': 'fake_pair_id'})
4190 helper_method = getattr(self.driver.plugin.helper, assert_method)
4191 mocker = self.mock_object(self.driver.plugin.helper,
4192 assert_method,
4193 mock.Mock(wraps=helper_method))
4194 self.driver.plugin.helper.custom_results[
4195 '/REPLICATIONPAIR/fake_pair_id'] = {
4196 "GET": """{"error":{"code":0},
4197 "data":%s}""" % pair_info}
4199 self.driver.update_replica_state(
4200 self._context,
4201 [self.active_replica, self.new_replica],
4202 self.new_replica,
4203 [], [], None)
4205 mocker.assert_called_with('fake_pair_id')
4207 @ddt.data({'pair_info': """{"HEALTHSTATUS": "1",
4208 "SECRESDATASTATUS": "2",
4209 "ISPRIMARY": "true",
4210 "SECRESACCESS": "1",
4211 "RUNNINGSTATUS": "1"}""",
4212 'assert_method': 'switch_replication_pair',
4213 'error_url': '/REPLICATIONPAIR/switch'},
4214 {'pair_info': """{"HEALTHSTATUS": "1",
4215 "SECRESDATASTATUS": "2",
4216 "ISPRIMARY": "false",
4217 "SECRESACCESS": "3",
4218 "RUNNINGSTATUS": "1"}""",
4219 'assert_method': 'set_pair_secondary_write_lock',
4220 'error_url': '/REPLICATIONPAIR/SET_SECODARY_WRITE_LOCK'},
4221 {'pair_info': """{"HEALTHSTATUS": "1",
4222 "SECRESDATASTATUS": "2",
4223 "ISPRIMARY": "false",
4224 "SECRESACCESS": "1",
4225 "RUNNINGSTATUS": "26"}""",
4226 'assert_method': 'sync_replication_pair',
4227 'error_url': '/REPLICATIONPAIR/sync'},)
4228 @ddt.unpack
4229 def test_update_replica_state_with_exception_ignore(
4230 self, pair_info, assert_method, error_url):
4231 self.driver.plugin.private_storage.update(
4232 'fake_share_id',
4233 {'replica_pair_id': 'fake_pair_id'})
4234 helper_method = getattr(self.driver.plugin.helper, assert_method)
4235 mocker = self.mock_object(self.driver.plugin.helper,
4236 assert_method,
4237 mock.Mock(wraps=helper_method))
4238 self.driver.plugin.helper.custom_results[
4239 error_url] = """{"error":{"code":-403}}"""
4240 self.driver.plugin.helper.custom_results[
4241 '/REPLICATIONPAIR/fake_pair_id'] = {
4242 "GET": """{"error":{"code":0},
4243 "data":%s}""" % pair_info}
4245 self.driver.update_replica_state(
4246 self._context,
4247 [self.active_replica, self.new_replica],
4248 self.new_replica,
4249 [], [], None)
4251 mocker.assert_called_once_with('fake_pair_id')
4253 def test_update_replica_state_with_replication_abnormal(self):
4254 self.driver.plugin.private_storage.update(
4255 'fake_share_id',
4256 {'replica_pair_id': 'fake_pair_id'})
4258 self.driver.plugin.helper.custom_results[
4259 '/REPLICATIONPAIR/fake_pair_id'] = {
4260 "GET": """{"error":{"code":0},
4261 "data":{"HEALTHSTATUS": "2"}}"""}
4263 result = self.driver.update_replica_state(
4264 self._context,
4265 [self.active_replica, self.new_replica],
4266 self.new_replica,
4267 [], [], None)
4269 self.assertEqual(common_constants.STATUS_ERROR, result)
4271 def test_update_replica_state_with_no_pair_id(self):
4272 result = self.driver.update_replica_state(
4273 self._context,
4274 [self.active_replica, self.new_replica],
4275 self.new_replica,
4276 [], [], None)
4278 self.assertEqual(common_constants.STATUS_ERROR, result)
4280 @ddt.data('true', 'false')
4281 def test_promote_replica_success(self, is_primary):
4282 self.driver.plugin.private_storage.update(
4283 'fake_share_id',
4284 {'replica_pair_id': 'fake_pair_id'})
4286 self.driver.plugin.helper.custom_results[
4287 '/REPLICATIONPAIR/fake_pair_id'] = {
4288 "GET": """{"error": {"code": 0},
4289 "data": {"HEALTHSTATUS": "1",
4290 "RUNNINGSTATUS": "1",
4291 "SECRESDATASTATUS": "2",
4292 "ISPRIMARY": "%s"}}""" % is_primary}
4294 result = self.driver.promote_replica(
4295 self._context,
4296 [self.active_replica, self.new_replica],
4297 self.new_replica,
4298 [], None)
4300 expected = [
4301 {'id': self.new_replica['id'],
4302 'replica_state': common_constants.REPLICA_STATE_ACTIVE,
4303 'access_rules_status': common_constants.STATUS_ACTIVE},
4304 {'id': self.active_replica['id'],
4305 'replica_state': common_constants.REPLICA_STATE_IN_SYNC,
4306 'access_rules_status':
4307 common_constants.SHARE_INSTANCE_RULES_SYNCING},
4308 ]
4310 self.assertEqual(expected, result)
4312 @ddt.data({'mock_method': 'update_access',
4313 'new_access_status':
4314 common_constants.SHARE_INSTANCE_RULES_SYNCING,
4315 'old_access_status':
4316 common_constants.SHARE_INSTANCE_RULES_SYNCING},
4317 {'mock_method': 'clear_access',
4318 'new_access_status':
4319 common_constants.SHARE_INSTANCE_RULES_SYNCING,
4320 'old_access_status': common_constants.STATUS_ACTIVE},)
4321 @ddt.unpack
4322 def test_promote_replica_with_access_update_error(
4323 self, mock_method, new_access_status, old_access_status):
4324 self.driver.plugin.private_storage.update(
4325 'fake_share_id',
4326 {'replica_pair_id': 'fake_pair_id'})
4328 self.driver.plugin.helper.custom_results[
4329 '/REPLICATIONPAIR/fake_pair_id'] = {
4330 "GET": """{"error": {"code": 0},
4331 "data": {"HEALTHSTATUS": "1",
4332 "RUNNINGSTATUS": "1",
4333 "SECRESDATASTATUS": "2",
4334 "ISPRIMARY": "false"}}"""}
4336 mocker = self.mock_object(self.driver.plugin,
4337 mock_method,
4338 mock.Mock(side_effect=Exception('err')))
4340 result = self.driver.promote_replica(
4341 self._context,
4342 [self.active_replica, self.new_replica],
4343 self.new_replica,
4344 [], None)
4346 expected = [
4347 {'id': self.new_replica['id'],
4348 'replica_state': common_constants.REPLICA_STATE_ACTIVE,
4349 'access_rules_status': new_access_status},
4350 {'id': self.active_replica['id'],
4351 'replica_state': common_constants.REPLICA_STATE_IN_SYNC,
4352 'access_rules_status': old_access_status},
4353 ]
4355 self.assertEqual(expected, result)
4356 mocker.assert_called()
4358 @ddt.data({'error_url': '/REPLICATIONPAIR/split',
4359 'assert_method': 'split_replication_pair'},
4360 {'error_url': '/REPLICATIONPAIR/switch',
4361 'assert_method': 'switch_replication_pair'},
4362 {'error_url': '/REPLICATIONPAIR/SET_SECODARY_WRITE_LOCK',
4363 'assert_method': 'set_pair_secondary_write_lock'},
4364 {'error_url': '/REPLICATIONPAIR/sync',
4365 'assert_method': 'sync_replication_pair'},)
4366 @ddt.unpack
4367 def test_promote_replica_with_error_ignore(self, error_url, assert_method):
4368 self.driver.plugin.private_storage.update(
4369 'fake_share_id',
4370 {'replica_pair_id': 'fake_pair_id'})
4371 helper_method = getattr(self.driver.plugin.helper, assert_method)
4372 mocker = self.mock_object(self.driver.plugin.helper,
4373 assert_method,
4374 mock.Mock(wraps=helper_method))
4375 self.driver.plugin.helper.custom_results[
4376 error_url] = '{"error":{"code":-403}}'
4377 fake_pair_infos = [{'ISPRIMARY': 'False',
4378 'HEALTHSTATUS': '1',
4379 'RUNNINGSTATUS': '1',
4380 'SECRESDATASTATUS': '1'},
4381 {'HEALTHSTATUS': '2'}]
4382 self.mock_object(self.driver.plugin.replica_mgr,
4383 '_get_replication_pair_info',
4384 mock.Mock(side_effect=fake_pair_infos))
4386 result = self.driver.promote_replica(
4387 self._context,
4388 [self.active_replica, self.new_replica],
4389 self.new_replica,
4390 [], None)
4392 expected = [
4393 {'id': self.new_replica['id'],
4394 'replica_state': common_constants.REPLICA_STATE_ACTIVE,
4395 'access_rules_status': common_constants.STATUS_ACTIVE},
4396 {'id': self.active_replica['id'],
4397 'replica_state': common_constants.STATUS_ERROR,
4398 'access_rules_status':
4399 common_constants.SHARE_INSTANCE_RULES_SYNCING},
4400 ]
4402 self.assertEqual(expected, result)
4403 mocker.assert_called_once_with('fake_pair_id')
4405 @ddt.data({'error_url': '/REPLICATIONPAIR/fake_pair_id',
4406 'url_result': """{"error":{"code":0},
4407 "data":{"HEALTHSTATUS": "1",
4408 "ISPRIMARY": "false",
4409 "RUNNINGSTATUS": "1",
4410 "SECRESDATASTATUS": "5"}}""",
4411 'expected_exception': exception.ReplicationException},
4412 {'error_url': '/REPLICATIONPAIR/CANCEL_SECODARY_WRITE_LOCK',
4413 'url_result': """{"error":{"code":-403}}""",
4414 'expected_exception': exception.InvalidShare},)
4415 @ddt.unpack
4416 def test_promote_replica_fail(self, error_url, url_result,
4417 expected_exception):
4418 self.driver.plugin.private_storage.update(
4419 'fake_share_id',
4420 {'replica_pair_id': 'fake_pair_id'})
4421 self.driver.plugin.helper.custom_results[error_url] = url_result
4423 self.assertRaises(expected_exception,
4424 self.driver.promote_replica,
4425 self._context,
4426 [self.active_replica, self.new_replica],
4427 self.new_replica,
4428 [], None)
4430 def test_promote_replica_with_no_pair_id(self):
4431 self.assertRaises(exception.ReplicationException,
4432 self.driver.promote_replica,
4433 self._context,
4434 [self.active_replica, self.new_replica],
4435 self.new_replica,
4436 [], None)
4438 @ddt.data({'url': '/REPLICATIONPAIR/split',
4439 'url_result': '{"error":{"code":-403}}'},
4440 {'url': '/REPLICATIONPAIR/fake_pair_id',
4441 'url_result': '{"error":{"code":1077937923}}'},
4442 {'url': '/REPLICATIONPAIR/fake_pair_id',
4443 'url_result': '{"error":{"code":0}}'},)
4444 @ddt.unpack
4445 def test_delete_replica_success(self, url, url_result):
4446 self.driver.plugin.private_storage.update(
4447 'fake_share_id',
4448 {'replica_pair_id': 'fake_pair_id'})
4449 self.driver.plugin.helper.custom_results['/filesystem/8'] = {
4450 "DELETE": '{"error":{"code":0}}'}
4451 self.driver.plugin.helper.custom_results[url] = url_result
4453 self.driver.delete_replica(self._context,
4454 [self.active_replica, self.new_replica],
4455 [], self.new_replica, None)
4456 self.assertIsNone(self.driver.plugin.private_storage.get(
4457 'fake_share_id', 'replica_pair_id'))
4459 @ddt.data({'url': '/REPLICATIONPAIR/fake_pair_id',
4460 'expected': 'fake_pair_id'},
4461 {'url': '/filesystem/8',
4462 'expected': None},)
4463 @ddt.unpack
4464 def test_delete_replica_fail(self, url, expected):
4465 self.driver.plugin.private_storage.update(
4466 'fake_share_id',
4467 {'replica_pair_id': 'fake_pair_id'})
4468 self.driver.plugin.helper.custom_results[url] = {
4469 "DELETE": '{"error":{"code":-403}}'}
4471 self.assertRaises(exception.InvalidShare,
4472 self.driver.delete_replica,
4473 self._context,
4474 [self.active_replica, self.new_replica],
4475 [], self.new_replica, None)
4476 self.assertEqual(expected,
4477 self.driver.plugin.private_storage.get(
4478 'fake_share_id', 'replica_pair_id'))
4480 def test_delete_replica_with_no_pair_id(self):
4481 self.driver.plugin.helper.custom_results['/filesystem/8'] = {
4482 "DELETE": '{"error":{"code":0}}'}
4484 self.driver.delete_replica(self._context,
4485 [self.active_replica, self.new_replica],
4486 [], self.new_replica, None)
4488 @ddt.data({'pair_info': """{"HEALTHSTATUS": "2"}""",
4489 'expected_state': common_constants.STATUS_ERROR},
4490 {'pair_info': """{"HEALTHSTATUS": "1",
4491 "RUNNINGSTATUS": "26"}""",
4492 'expected_state': common_constants.REPLICA_STATE_OUT_OF_SYNC},
4493 {'pair_info': """{"HEALTHSTATUS": "1",
4494 "RUNNINGSTATUS": "33"}""",
4495 'expected_state': common_constants.REPLICA_STATE_OUT_OF_SYNC},
4496 {'pair_info': """{"HEALTHSTATUS": "1",
4497 "RUNNINGSTATUS": "34"}""",
4498 'expected_state': common_constants.STATUS_ERROR},
4499 {'pair_info': """{"HEALTHSTATUS": "1",
4500 "RUNNINGSTATUS": "35"}""",
4501 'expected_state': common_constants.STATUS_ERROR},
4502 {'pair_info': """{"HEALTHSTATUS": "1",
4503 "SECRESDATASTATUS": "1",
4504 "RUNNINGSTATUS": "1"}""",
4505 'expected_state': common_constants.REPLICA_STATE_IN_SYNC},
4506 {'pair_info': """{"HEALTHSTATUS": "1",
4507 "SECRESDATASTATUS": "2",
4508 "RUNNINGSTATUS": "1"}""",
4509 'expected_state': common_constants.REPLICA_STATE_IN_SYNC},
4510 {'pair_info': """{"HEALTHSTATUS": "1",
4511 "SECRESDATASTATUS": "5",
4512 "RUNNINGSTATUS": "1"}""",
4513 'expected_state': common_constants.REPLICA_STATE_OUT_OF_SYNC})
4514 @ddt.unpack
4515 def test_get_replica_state(self, pair_info, expected_state):
4516 self.driver.plugin.helper.custom_results[
4517 '/REPLICATIONPAIR/fake_pair_id'] = {
4518 "GET": """{"error":{"code":0},
4519 "data":%s}""" % pair_info}
4521 result_state = self.driver.plugin.replica_mgr.get_replica_state(
4522 'fake_pair_id')
4524 self.assertEqual(expected_state, result_state)
4526 @ddt.data(*constants.QOS_STATUSES)
4527 def test_delete_qos(self, qos_status):
4528 self.driver.plugin.helper.custom_results['/ioclass/11'] = {
4529 "GET": """{"error":{"code":0}, "data":{"RUNNINGSTATUS": "%s"}}""" %
4530 qos_status
4531 }
4533 activate_deactivate_qos_mock = self.mock_object(
4534 self.driver.plugin.helper,
4535 'activate_deactivate_qos')
4536 delete_qos_mock = self.mock_object(
4537 self.driver.plugin.helper,
4538 'delete_qos_policy')
4540 qos = smartx.SmartQos(self.driver.plugin.helper)
4541 qos.delete_qos('11')
4543 if qos_status == constants.STATUS_QOS_INACTIVATED:
4544 activate_deactivate_qos_mock.assert_not_called()
4545 else:
4546 activate_deactivate_qos_mock.assert_called_once_with('11', False)
4548 delete_qos_mock.assert_called_once_with('11')
4550 def test_username_password_encode_decode(self):
4551 for i in (1, 2):
4552 # First loop will encode the username/password and
4553 # write back to configuration.
4554 # Second loop will get the encoded username/password and
4555 # decode them.
4556 logininfo = self.driver.plugin.helper._get_login_info()
4557 self.assertEqual('admin', logininfo['UserName'])
4558 self.assertEqual('Admin@storage', logininfo['UserPassword'])
4560 @ddt.data({
4561 'username': 'abc',
4562 'password': '123456',
4563 'expect_username': 'abc',
4564 'expect_password': '123456',
4565 }, {
4566 'username': '!$$$YWJj',
4567 'password': '!$$$MTIzNDU2',
4568 'expect_username': 'abc',
4569 'expect_password': '123456',
4570 }, {
4571 'username': 'ab!$$$c',
4572 'password': '123!$$$456',
4573 'expect_username': 'ab!$$$c',
4574 'expect_password': '123!$$$456',
4575 })
4576 @ddt.unpack
4577 def test__get_login_info(self, username, password, expect_username,
4578 expect_password):
4579 configs = {
4580 'Storage/RestURL': 'https://123456',
4581 'Storage/UserName': username,
4582 'Storage/UserPassword': password,
4583 }
4584 self.mock_object(
4585 ET, 'parse',
4586 mock.Mock(return_value=FakeConfigParseTree(configs)))
4588 result = self.driver.plugin.helper._get_login_info()
4589 self.assertEqual(expect_username, result['UserName'])
4590 self.assertEqual(expect_password, result['UserPassword'])
4591 ET.parse.assert_called_once_with(self.fake_conf_file)
4593 def test_revert_to_snapshot_success(self):
4594 snapshot = {'id': 'fake-fs-id',
4595 'share_name': 'share_fake_uuid'}
4596 with mock.patch.object(
4597 self.driver.plugin.helper, 'call') as mock_call:
4598 mock_call.return_value = {
4599 "error": {"code": 0},
4600 "data": [{"ID": "4", "NAME": "share_fake_uuid"}]
4601 }
4602 self.driver.revert_to_snapshot(None, snapshot, None, None)
4603 expect_snapshot_id = "4@share_snapshot_fake_fs_id"
4604 mock_call.assert_called_with(
4605 "/FSSNAPSHOT/ROLLBACK_FSSNAPSHOT",
4606 jsonutils.dumps({"ID": expect_snapshot_id}), 'PUT')
4608 def test_revert_to_snapshot_exception(self):
4609 snapshot = {'id': 'fake-snap-id',
4610 'share_name': 'not_exist_share_name',
4611 'share_id': 'fake_share_id'}
4612 self.assertRaises(exception.ShareResourceNotFound,
4613 self.driver.revert_to_snapshot,
4614 None, snapshot, None, None)
4616 @ddt.data({'name': 'fake_name',
4617 'share_proto': 'NFS',
4618 'mount_path': 'fake_nfs_mount_path',
4619 'mount_src': '/mnt/test'},
4620 {'name': 'fake_name',
4621 'share_proto': 'CIFS',
4622 'mount_path': 'fake_cifs_mount_path',
4623 'mount_src': '/mnt/test'},
4624 )
4625 def test_mount_share_to_host(self, share):
4626 access = {'access_to': 'cifs_user',
4627 'access_password': 'cifs_password'}
4628 mocker = self.mock_object(utils, 'execute')
4629 self.driver.plugin.mount_share_to_host(share, access)
4630 if share['share_proto'] == 'NFS':
4631 mocker.assert_called_once_with(
4632 'mount', '-t', 'nfs', 'fake_nfs_mount_path', '/mnt/test',
4633 run_as_root=True)
4634 else:
4635 mocker.assert_called_once_with(
4636 'mount', '-t', 'cifs', 'fake_cifs_mount_path', '/mnt/test',
4637 '-o', 'username=cifs_user,password=cifs_password',
4638 run_as_root=True)
4641@ddt.ddt
4642class HuaweiDriverHelperTestCase(test.TestCase):
4643 def setUp(self):
4644 super(HuaweiDriverHelperTestCase, self).setUp()
4645 self.helper = helper.RestHelper(None)
4647 def test_init_http_head(self):
4648 self.helper.init_http_head()
4649 self.assertIsNone(self.helper.url)
4650 self.assertFalse(self.helper.session.verify)
4651 self.assertEqual("keep-alive",
4652 self.helper.session.headers["Connection"])
4653 self.assertEqual("application/json",
4654 self.helper.session.headers["Content-Type"])
4656 @ddt.data(('fake_data', 'POST'),
4657 (None, 'POST'),
4658 (None, 'PUT'),
4659 (None, 'GET'),
4660 ('fake_data', 'PUT'),
4661 (None, 'DELETE'),
4662 )
4663 @ddt.unpack
4664 def test_do_call_with_valid_method(self, data, method):
4665 self.helper.init_http_head()
4667 mocker = self.mock_object(self.helper.session, method.lower())
4668 self.helper.do_call("fake-rest-url", data, method)
4670 kwargs = {'timeout': constants.SOCKET_TIMEOUT}
4671 if data:
4672 kwargs['data'] = data
4673 mocker.assert_called_once_with("fake-rest-url", **kwargs)
4675 def test_do_call_with_invalid_method(self):
4676 self.assertRaises(exception.ShareBackendException,
4677 self.helper.do_call,
4678 "fake-rest-url", None, 'fake-method')
4680 def test_do_call_with_http_error(self):
4681 self.helper.init_http_head()
4683 fake_res = requests.Response()
4684 fake_res.reason = 'something wrong'
4685 fake_res.status_code = 500
4686 fake_res.url = "fake-rest-url"
4688 self.mock_object(self.helper.session, 'post',
4689 mock.Mock(return_value=fake_res))
4690 res = self.helper.do_call("fake-rest-url", None, 'POST')
4692 expected = {
4693 "error": {
4694 "code": 500,
4695 "description": '500 Server Error: something wrong for '
4696 'url: fake-rest-url'}
4697 }
4698 self.assertDictEqual(expected, res)