Coverage for manila/tests/share/drivers/dell_emc/common/enas/fakes.py: 99%
498 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) 2015 EMC Corporation.
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
16from unittest import mock
18from oslo_utils import units
20from manila.common import constants as const
21from manila.share import configuration as conf
22from manila.share.drivers.dell_emc.common.enas import utils
23from manila.tests import fake_share
26def query(func):
27 def inner(*args, **kwargs):
28 return (
29 '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
30 '<RequestPacket xmlns="http://www.emc.com/schemas/celerra/'
31 'xml_api"><Request><Query>'
32 + func(*args, **kwargs)
33 + '</Query></Request></RequestPacket>'
34 )
36 return inner
39def start_task(func):
40 def inner(*args, **kwargs):
41 return (
42 '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
43 '<RequestPacket xmlns="http://www.emc.com/schemas/celerra/'
44 'xml_api"><Request><StartTask timeout="300">'
45 + func(*args, **kwargs)
46 + '</StartTask></Request></RequestPacket>')
48 return inner
51def response(func):
52 def inner(*args, **kwargs):
53 return (
54 '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
55 '<ResponsePacket xmlns="http://www.emc.com/schemas/celerra/'
56 'xml_api"><Response>'
57 + func(*args, **kwargs)
58 + '</Response></ResponsePacket>'
59 ).encode()
61 return inner
64class FakeData(object):
65 # Share information
66 share_id = '7cf7c200_d3af_4e05_b87e_9167c95df4f9'
67 host = 'HostA@BackendB#fake_pool_name'
68 share_name = share_id
69 share_size = 10
70 new_size = 20
71 src_share_name = '7cf7c200_d3af_4e05_b87e_9167c95df4f0'
73 # Snapshot information
74 snapshot_name = 'de4c9050-e2f9-4ce1-ade4-5ed0c9f26451'
75 src_snap_name = 'de4c9050-e2f9-4ce1-ade4-5ed0c9f26452'
76 snapshot_id = 'fake_snap_id'
77 snapshot_size = 10 * units.Ki
79 # Share network information
80 share_network_id = 'c5b3a865-56d0-4d88-abe5-879965e099c9'
81 cidr = '192.168.1.0/24'
82 cidr_v6 = 'fdf8:f53b:82e1::/64'
83 segmentation_id = 100
84 network_allocations_id1 = '132dbb10-9a36-46f2-8d89-3d909830c356'
85 network_allocations_id2 = '7eabdeed-bad2-46ea-bd0f-a33884c869e0'
86 network_allocations_id3 = '98c9e490-a842-4e59-b59a-a6042069d35b'
87 network_allocations_id4 = '6319a917-ab95-4b65-a498-773ae33c5550'
88 network_allocations_ip1 = '192.168.1.1'
89 network_allocations_ip2 = '192.168.1.2'
90 network_allocations_ip3 = 'fdf8:f53b:82e1::1'
91 network_allocations_ip4 = 'fdf8:f53b:82e1::2'
93 network_allocations_ip_version1 = 4
94 network_allocations_ip_version2 = 4
95 network_allocations_ip_version3 = 6
96 network_allocations_ip_version4 = 6
97 domain_name = 'fake_domain'
98 domain_user = 'administrator'
99 domain_password = 'password'
100 dns_ip_address = '192.168.1.200'
101 dns_ipv6_address = 'fdf8:f53b:82e1::f'
103 # Share server information
104 share_server_id = '56aafd02-4d44-43d7-b784-57fc88167224'
106 # Filesystem information
107 filesystem_name = share_name
108 filesystem_id = 'fake_filesystem_id'
109 filesystem_size = 10 * units.Ki
110 filesystem_new_size = 20 * units.Ki
112 # Mountpoint information
113 path = '/' + share_name
115 # Mover information
116 mover_name = 'server_2'
117 mover_id = 'fake_mover_id'
118 interface_name1 = network_allocations_id1[-12:]
119 interface_name2 = network_allocations_id2[-12:]
120 interface_name3 = network_allocations_id3[-12:]
121 interface_name4 = network_allocations_id4[-12:]
122 long_interface_name = network_allocations_id1
123 net_mask = '255.255.255.0'
124 net_mask_v6 = 64
125 device_name = 'cge-1-0'
126 interconnect_id = '2001'
128 # VDM information
129 vdm_name = share_server_id
130 vdm_id = 'fake_vdm_id'
132 # Pool information
133 pool_name = 'fake_pool_name'
134 pool_id = 'fake_pool_id'
135 pool_used_size = 20480
136 pool_total_size = 511999
138 # NFS share access information
139 rw_hosts = ['192.168.1.1', '192.168.1.2']
140 ro_hosts = ['192.168.1.3', '192.168.1.4']
141 nfs_host_ip = '192.168.1.5'
142 rw_hosts_ipv6 = ['fdf8:f53b:82e1::1', 'fdf8:f53b:82e1::2']
143 ro_hosts_ipv6 = ['fdf8:f53b:82e1::3', 'fdf8:f53b:82e1::4']
144 nfs_host_ipv6 = 'fdf8:f53b:82e1::5'
146 fake_output = ''
148 fake_error_msg = 'fake error message'
150 emc_share_backend = 'vnx'
151 powermax_share_backend = 'powermax'
152 emc_nas_server = '192.168.1.20'
153 emc_nas_login = 'fakename'
154 emc_nas_password = 'fakepassword'
155 share_backend_name = 'EMC_NAS_Storage'
157 cifs_access = """
158 1478607389: SMB:11: Unix user 'Guest' UID=32769
159 1478607389: SMB:10: FindUserUid:Access_Password 'Guest',1=0x8001 T=0
160 1478607389: SHARE: 6: ALLOWED:fullcontrol:S-1-5-15-3399d125-6dcdf5f4
161 1478607389: SMB:11: Unix user 'Administrator' UID=32768
162 1478607389: SMB:10: FindUserUid:Access_Password 'Administrator',
163 1478607389: SHARE: 6: ALLOWED:fullcontrol:S-1-5-15-3399d125
164 """
167class StorageObjectTestData(object):
168 def __init__(self):
169 self.share_name = FakeData.share_name
171 self.filesystem_name = FakeData.filesystem_name
172 self.filesystem_id = FakeData.filesystem_id
173 self.filesystem_size = 10 * units.Ki
174 self.filesystem_new_size = 20 * units.Ki
176 self.path = FakeData.path
178 self.snapshot_name = FakeData.snapshot_name
179 self.snapshot_id = FakeData.snapshot_id
180 self.snapshot_size = 10 * units.Ki
182 self.src_snap_name = FakeData.src_snap_name
183 self.src_fileystems_name = FakeData.src_share_name
185 self.mover_name = FakeData.mover_name
186 self.mover_id = FakeData.mover_id
187 self.vdm_name = FakeData.vdm_name
188 self.vdm_id = FakeData.vdm_id
190 self.pool_name = FakeData.pool_name
191 self.pool_id = FakeData.pool_id
192 self.pool_used_size = FakeData.pool_used_size
193 self.pool_total_size = FakeData.pool_total_size
195 self.interface_name1 = FakeData.interface_name1
196 self.interface_name2 = FakeData.interface_name2
197 self.interface_name3 = FakeData.interface_name3
198 self.interface_name4 = FakeData.interface_name4
199 self.long_interface_name = FakeData.long_interface_name
200 self.ip_address1 = FakeData.network_allocations_ip1
201 self.ip_address2 = FakeData.network_allocations_ip2
202 self.ip_address3 = FakeData.network_allocations_ip3
203 self.ip_address4 = FakeData.network_allocations_ip4
204 self.net_mask = FakeData.net_mask
205 self.net_mask_v6 = FakeData.net_mask_v6
206 self.vlan_id = FakeData.segmentation_id
208 self.cifs_server_name = FakeData.vdm_name
210 self.domain_name = FakeData.domain_name
211 self.domain_user = FakeData.domain_user
212 self.domain_password = FakeData.domain_password
213 self.dns_ip_address = FakeData.dns_ip_address
215 self.device_name = FakeData.device_name
217 self.interconnect_id = FakeData.interconnect_id
219 self.rw_hosts = FakeData.rw_hosts
220 self.ro_hosts = FakeData.ro_hosts
221 self.nfs_host_ip = FakeData.nfs_host_ip
223 self.rw_hosts_ipv6 = FakeData.rw_hosts_ipv6
224 self.ro_hosts_ipv6 = FakeData.ro_hosts_ipv6
225 self.nfs_host_ipv6 = FakeData.nfs_host_ipv6
227 self.fake_output = FakeData.fake_output
229 @response
230 def resp_get_error(self):
231 return (
232 '<QueryStatus maxSeverity="error">'
233 '<Problem messageCode="18522112101" facility="Generic" '
234 'component="API" message="Fake message." severity="error">'
235 '<Description>Fake description.</Description>'
236 '<Action>Fake action.</Action>'
237 '<Diagnostics>Fake diagnostics.</Diagnostics>'
238 '</Problem>'
239 '<Problem messageCode="18522112101" facility="Generic" '
240 'component="API" message="Fake message." severity="error">'
241 '<Description>Fake description.</Description>'
242 '<Action>Fake action.</Action>'
243 '<Diagnostics>Fake diagnostics.</Diagnostics>'
244 '</Problem>'
245 '</QueryStatus> '
246 )
248 @response
249 def resp_get_without_value(self):
250 return (
251 '<QueryStatus maxSeverity="ok"/>'
252 )
254 @response
255 def resp_task_succeed(self):
256 return (
257 '<TaskResponse taskId="123">'
258 '<Status maxSeverity="ok"/>'
259 '</TaskResponse>'
260 )
262 @response
263 def resp_task_error(self):
264 return (
265 '<TaskResponse taskId="123">'
266 '<Status maxSeverity="error"/>'
267 '</TaskResponse>'
268 )
270 @response
271 def resp_invalid_mover_id(self):
272 return (
273 '<Fault maxSeverity="error">'
274 '<Problem messageCode="14227341323" facility="Prevalidator" '
275 'component="API" message="Mover with id=100 not found." '
276 'severity="error">'
277 '<Description>The Mover ID supplied with the request is invalid.'
278 '</Description>'
279 '<Action>Refer to the XML API v2 schema/documentation and correct '
280 'your user program logic.</Action>'
281 '<Diagnostics> Exception tag: 14fb692e556 Exception '
282 'message: com.emc.nas.ccmd.common.MessageInstanceImpl@5004000d '
283 '</Diagnostics>'
284 '</Problem>'
285 '</Fault> '
286 )
288 @response
289 def resp_need_retry(self):
290 return ('<TaskResponse taskId="915525">'
291 '<Status maxSeverity = "error">'
292 '<Problem messageCode = "13421840537" component = "fake"'
293 ' message = "unable to acquire lock(s), try later"'
294 ' severity = "error" >'
295 '<Description> fake desp. </Description>'
296 '<Action>fake action </Action>'
297 '</Problem></Status></TaskResponse>')
299 @start_task
300 def req_fake_start_task(self):
301 return '<StartFake name="foo"></StartFake>'
304class FileSystemTestData(StorageObjectTestData):
305 def __init__(self):
306 super(FileSystemTestData, self).__init__()
308 @start_task
309 def req_create_on_vdm(self):
310 return (
311 '<NewFileSystem name="%(name)s">'
312 '<Vdm vdm="%(id)s"/>'
313 '<StoragePool mayContainSlices="true" pool="%(pool_id)s" '
314 'size="%(size)s"/>'
315 '</NewFileSystem>'
316 % {'name': self.filesystem_name,
317 'id': self.vdm_id,
318 'pool_id': self.pool_id,
319 'size': self.filesystem_size}
320 )
322 @start_task
323 def req_create_on_mover(self):
324 return (
325 '<NewFileSystem name="%(name)s">'
326 '<Mover mover="%(id)s"/>'
327 '<StoragePool mayContainSlices="true" pool="%(pool_id)s" '
328 'size="%(size)s"/>'
329 '</NewFileSystem>'
330 % {'name': self.filesystem_name,
331 'id': self.mover_id,
332 'pool_id': self.pool_id,
333 'size': self.filesystem_size}
334 )
336 @response
337 def resp_create_but_already_exist(self):
338 return (
339 ' <TaskResponse taskId="31362">'
340 '<Status maxSeverity="error">'
341 '<Problem messageCode="13691191325" component="APL" '
342 'message="A file system with the name fake_filesystem '
343 'already exists." severity="error">'
344 '<Description></Description>'
345 '<Action></Action>'
346 '</Problem>'
347 '</Status>'
348 '</TaskResponse> '
349 )
351 @start_task
352 def req_delete(self):
353 return (
354 '<DeleteFileSystem fileSystem="%(id)s"/>' %
355 {'id': self.filesystem_id}
356 )
358 @response
359 def resp_delete_but_failed(self):
360 return (
361 '<Fault maxSeverity="error">'
362 '<Problem messageCode="14227341326" facility="Prevalidator" '
363 'component="API" message="File system with id=77777 not found." '
364 'severity="error">'
365 '<Description>The file system ID supplied with the request is '
366 'invalid.</Description>'
367 '<Action>Refer to the XML API v2 schema/documentation and correct '
368 'your user program logic.</Action>'
369 '<Diagnostics> Exception tag: 14fb6b6a7b8 Exception '
370 'message: com.emc.nas.ccmd.common.MessageInstanceImpl@5004000e '
371 '</Diagnostics>'
372 '</Problem>'
373 '</Fault> '
374 )
376 @start_task
377 def req_extend(self):
378 return (
379 '<ExtendFileSystem fileSystem="%(id)s">'
380 '<StoragePool pool="%(pool_id)s" size="%(size)d"/>'
381 '</ExtendFileSystem>' %
382 {'id': self.filesystem_id,
383 'pool_id': self.pool_id,
384 'size': self.filesystem_new_size - self.filesystem_size}
385 )
387 @response
388 def resp_extend_but_error(self):
389 return (
390 '<Fault maxSeverity="error">'
391 '<Problem messageCode="14227341325" facility="Prevalidator" '
392 'component="API" message="Fake message.">'
393 '<Description>Fake description.</Description>'
394 '<Action>Fake action.</Action>'
395 '<Diagnostics> Fake diagnostics.</Diagnostics>'
396 '</Problem>'
397 '</Fault> '
398 )
400 @query
401 def req_get(self):
402 return (
403 '<FileSystemQueryParams>'
404 '<AspectSelection fileSystemCapacityInfos="true" '
405 'fileSystems="true"/>'
406 '<Alias name="%(name)s"/>'
407 '</FileSystemQueryParams>' %
408 {'name': self.filesystem_name}
409 )
411 @response
412 def resp_get_succeed(self):
413 return (
414 '<QueryStatus maxSeverity="ok"/>'
415 '<FileSystem name="%(name)s" type="uxfs" volume="107" '
416 'storagePools="%(pool_id)s" storages="1" containsSlices="true" '
417 'internalUse="false" dataServicePolicies="Thin=No,Compressed=No,'
418 'Mirrored=No,Tiering policy=Auto-Tier/Highest Available Tier" '
419 'fileSystem="%(id)s">'
420 '<ProductionFileSystemData cwormState="off"/>'
421 '</FileSystem>'
422 '<FileSystemCapacityInfo volumeSize="%(size)s" '
423 'fileSystem="%(id)s"/>' %
424 {'name': self.filesystem_name,
425 'id': self.filesystem_id,
426 'size': self.filesystem_size,
427 'pool_id': self.pool_id}
428 )
430 @response
431 def resp_get_but_miss_property(self):
432 return (
433 '<QueryStatus maxSeverity="ok"/>'
434 '<FileSystem name="%(name)s" type="uxfs" volume="107" '
435 'storagePools="%(pool_id)s" storages="1" containsSlices="true" '
436 'internalUse="false" '
437 'fileSystem="%(id)s">'
438 '<ProductionFileSystemData cwormState="off"/>'
439 '</FileSystem>'
440 '<FileSystemCapacityInfo volumeSize="%(size)s" '
441 'fileSystem="%(id)s"/>' %
442 {'name': self.filesystem_name,
443 'id': self.filesystem_id,
444 'size': self.filesystem_size,
445 'pool_id': self.pool_id}
446 )
448 @response
449 def resp_get_but_not_found(self):
450 return (
451 '<QueryStatus maxSeverity="warning">'
452 '<Problem messageCode="18522112101" facility="Generic" '
453 'component="API" message="The query may be incomplete or '
454 'requested object not found." severity="warning">'
455 '<Description>The query may be incomplete because some of the '
456 'Celerra components are unavailable or do not exist. Another '
457 'reason may be application error. </Description>'
458 '<Action>If the entire Celerra is functioning correctly, '
459 'check your client application logic. </Action>'
460 '<Diagnostics>File system not found.</Diagnostics>'
461 '</Problem>'
462 '<Problem messageCode="18522112101" facility="Generic" '
463 'component="API" message="The query may be incomplete or '
464 'requested object not found." severity="warning">'
465 '<Description>The query may be incomplete because some of the '
466 'Celerra components are unavailable or do not exist. Another '
467 'reason may be application error.</Description>'
468 '<Action>If the entire Celerra is functioning correctly, '
469 'check your client application logic.</Action>'
470 '<Diagnostics>Migration file system not found.</Diagnostics>'
471 '</Problem>'
472 '</QueryStatus> '
473 )
475 def cmd_create_from_ckpt(self):
476 return [
477 'env', 'NAS_DB=/nas', '/nas/bin/nas_fs',
478 '-name', self.filesystem_name,
479 '-type', 'uxfs',
480 '-create',
481 'samesize=' + self.src_fileystems_name,
482 'pool=' + self.pool_name,
483 'storage=SINGLE',
484 'worm=off',
485 '-thin', 'no',
486 '-option', 'slice=y',
487 ]
489 def cmd_copy_ckpt(self):
490 session_name = self.filesystem_name + ':' + self.src_snap_name
492 return [
493 'env', 'NAS_DB=/nas', '/nas/bin/nas_copy',
494 '-name', session_name[0:63],
495 '-source', '-ckpt', self.src_snap_name,
496 '-destination', '-fs', self.filesystem_name,
497 '-interconnect', "id=" + self.interconnect_id,
498 '-overwrite_destination',
499 '-full_copy',
500 ]
502 output_copy_ckpt = "OK"
503 error_copy_ckpt = "ERROR"
505 def cmd_nas_fs_info(self):
506 return [
507 'env', 'NAS_DB=/nas', '/nas/bin/nas_fs',
508 '-info', self.filesystem_name,
509 ]
511 def output_info(self):
512 return (
513 """output = id = 515
514 name = %(share_name)s
515 acl = 0
516 in_use = True
517 type = uxfs
518 worm = off
519 volume = v993
520 deduplication = Off
521 thin_storage = True
522 tiering_policy = Auto-Tier/Optimize Pool
523 compressed= False
524 mirrored = False
525 ckpts = %(ckpt)s
526 stor_devs = FNM00124500890-004B
527 disks = d7
528 disk=d7 fakeinfo""" %
529 {'share_name': self.filesystem_name,
530 'ckpt': self.snapshot_name})
532 def cmd_delete(self):
533 return [
534 'env', 'NAS_DB=/nas', '/nas/bin/nas_fs',
535 '-delete', self.snapshot_name,
536 '-Force',
537 ]
540class SnapshotTestData(StorageObjectTestData):
541 def __init__(self):
542 super(SnapshotTestData, self).__init__()
544 @start_task
545 def req_create(self):
546 return (
547 '<NewCheckpoint checkpointOf="%(fsid)s" '
548 'name="%(name)s"><SpaceAllocationMethod>'
549 '<StoragePool pool="%(pool_id)s"/></SpaceAllocationMethod>'
550 '</NewCheckpoint>'
551 % {'fsid': self.filesystem_id,
552 'name': self.snapshot_name,
553 'pool_id': self.pool_id}
554 )
556 @start_task
557 def req_create_with_size(self):
558 return (
559 '<NewCheckpoint checkpointOf="%(fsid)s" '
560 'name="%(name)s"><SpaceAllocationMethod>'
561 '<StoragePool pool="%(pool_id)s" size="%(size)s"/>'
562 '</SpaceAllocationMethod>'
563 '</NewCheckpoint>'
564 % {'fsid': self.filesystem_id,
565 'name': self.snapshot_name,
566 'pool_id': self.pool_id,
567 'size': self.snapshot_size}
568 )
570 @response
571 def resp_create_but_already_exist(self):
572 return (
573 '<Status maxSeverity="error">'
574 '<Problem messageCode="13690535947" component="APL" '
575 'message="snap_0 is already in use." severity="error">'
576 '<Description></Description>'
577 '<Action></Action>'
578 '</Problem>'
579 '</Status>'
580 )
582 @query
583 def req_get(self):
584 return (
585 '<CheckpointQueryParams><Alias name="%(name)s"/>'
586 '</CheckpointQueryParams>'
587 % {'name': self.snapshot_name}
588 )
590 @response
591 def resp_get_succeed(self):
592 return (
593 '<QueryStatus maxSeverity="ok"/>'
594 '<Checkpoint checkpointOf="%(fs_id)s" name="%(name)s_replica1"'
595 ' state="active" time="1405428355" fileSystemSize="0"'
596 ' checkpoint="%(snap_id)s"/>'
597 % {'name': self.snapshot_name,
598 'fs_id': self.filesystem_id,
599 'snap_id': self.snapshot_id}
600 )
602 @start_task
603 def req_delete(self):
604 return (
605 '<DeleteCheckpoint checkpoint="%(id)s"/>' %
606 {'id': self.snapshot_id}
607 )
610class MountPointTestData(StorageObjectTestData):
611 def __init__(self):
612 super(MountPointTestData, self).__init__()
614 @start_task
615 def req_create(self, mover_id, is_vdm=True):
616 return (
617 '<NewMount path="%(path)s" fileSystem="%(fs_id)s">'
618 '<MoverOrVdm mover="%(mover_id)s" moverIdIsVdm="%(is_vdm)s"/>'
619 '</NewMount>' %
620 {'path': self.path,
621 'fs_id': self.filesystem_id,
622 'mover_id': mover_id,
623 'is_vdm': 'true' if is_vdm else 'false'}
624 )
626 @response
627 def resp_create_but_already_exist(self):
628 return (
629 '<TaskResponse taskId="31428">'
630 '<Status maxSeverity="error">'
631 '<Problem messageCode="13690601492" component="APL" '
632 'message="Mount already exists" severity="error">'
633 '<Description></Description> <Action></Action>'
634 '</Problem>'
635 '</Status>'
636 '</TaskResponse> ')
638 @start_task
639 def req_delete(self, mover_id, is_vdm=True):
640 return (
641 '<DeleteMount path="%(path)s" mover="%(mover_id)s" '
642 'moverIdIsVdm="%(is_vdm)s"/>' %
643 {'path': self.path,
644 'mover_id': mover_id,
645 'is_vdm': 'true' if is_vdm else 'false'}
646 )
648 @response
649 def resp_delete_but_nonexistent(self):
650 return (
651 '<TaskResponse taskId="31401">'
652 '<Status maxSeverity="error"> <Problem messageCode="13690601492" '
653 'component="APL" message="/fake_filesystem : No such path or '
654 'invalid operation." severity="error">'
655 '<Description></Description> <Action></Action>'
656 '</Problem>'
657 '</Status>'
658 '</TaskResponse> '
659 )
661 @query
662 def req_get(self, mover_id, is_vdm=True):
663 return (
664 '<MountQueryParams><MoverOrVdm mover="%(mover_id)s" '
665 'moverIdIsVdm="%(is_vdm)s"/></MountQueryParams>' %
666 {'mover_id': mover_id,
667 'is_vdm': 'true' if is_vdm else 'false'}
668 )
670 @response
671 def resp_get_succeed(self, mover_id, is_vdm=True):
672 return (
673 '<QueryStatus maxSeverity="ok"/>'
674 '<Mount fileSystem="%(fsID)s" disabled="false"'
675 ' ntCredential="false" path="%(path)s" mover="%(mover_id)s"'
676 ' moverIdIsVdm="%(is_vdm)s">'
677 '<NfsOptions ro="false" virusScan="true"'
678 ' prefetch="true" uncached="false"/>'
679 '<CifsOptions cifsSyncwrite="false" notify="true"'
680 ' triggerLevel="512" notifyOnAccess="false"'
681 ' notifyOnWrite="false" oplock="true" accessPolicy="NATIVE"'
682 ' lockingPolicy="nolock"/></Mount>'
683 % {'path': self.path,
684 'fsID': self.filesystem_id,
685 'mover_id': mover_id,
686 'is_vdm': 'true' if is_vdm else 'false'}
687 )
689 def cmd_server_mount(self, mode):
690 return [
691 'env', 'NAS_DB=/nas', '/nas/bin/server_mount', self.vdm_name,
692 '-option', mode,
693 self.filesystem_name,
694 self.path,
695 ]
697 def cmd_server_umount(self):
698 return [
699 'env', 'NAS_DB=/nas', '/nas/bin/server_umount', self.vdm_name,
700 '-perm', self.snapshot_name,
701 ]
704class VDMTestData(StorageObjectTestData):
705 def __init__(self):
706 super(VDMTestData, self).__init__()
708 @start_task
709 def req_create(self):
710 return (
711 '<NewVdm mover="%(mover_id)s" name="%(vdm_name)s"/>' %
712 {'mover_id': self.mover_id, 'vdm_name': self.vdm_name}
713 )
715 @response
716 def resp_create_but_already_exist(self):
717 return (
718 '<TaskResponse taskId="32551">'
719 '<Status maxSeverity="error">'
720 '<Problem messageCode="13421840550" component="CS_CORE" '
721 'message="VDM_01 : an entry with this name already exists" '
722 'severity="error">'
723 '<Description>Duplicate name specified</Description>'
724 '<Action>Specify a unqiue name</Action>'
725 '</Problem>'
726 '<Problem messageCode="13421840550" component="CS_CORE" '
727 'message="VDM_01 : an entry with this name already exists" '
728 'severity="error">'
729 '<Description>Duplicate name specified</Description>'
730 '<Action>Specify a unqiue name</Action>'
731 '</Problem>'
732 '</Status>'
733 '</TaskResponse> '
734 )
736 @query
737 def req_get(self):
738 return '<VdmQueryParams/>'
740 @response
741 def resp_get_succeed(self, name=None, interface1=None, interface2=None):
742 if name is None:
743 name = self.vdm_name
745 if interface1 is None:
746 interface1 = self.interface_name1
748 if interface2 is None:
749 interface2 = self.interface_name2
751 return (
752 '<QueryStatus maxSeverity="ok"/>'
753 '<Vdm name="%(vdm_name)s" state="loaded" mover="%(mover_id)s" '
754 'rootFileSystem="396" vdm="%(vdm_id)s">'
755 '<Status maxSeverity="ok"/>'
756 '<Interfaces> <li>%(interface1)s</li> <li>%(interface2)s</li>'
757 '</Interfaces> </Vdm>' %
758 {'vdm_name': name,
759 'vdm_id': self.vdm_id,
760 'mover_id': self.mover_id,
761 'interface1': interface1,
762 'interface2': interface2}
763 )
765 @response
766 def resp_get_but_not_found(self):
767 return (
768 '<QueryStatus maxSeverity="ok"/>'
769 )
771 @start_task
772 def req_delete(self):
773 return '<DeleteVdm vdm="%(vdmid)s"/>' % {'vdmid': self.vdm_id}
775 def cmd_attach_nfs_interface(self, interface=None):
776 if interface is None:
777 interface = self.interface_name2
779 return [
780 'env', 'NAS_DB=/nas', '/nas/bin/nas_server',
781 '-vdm', self.vdm_name,
782 '-attach', interface,
783 ]
785 def cmd_detach_nfs_interface(self):
786 return [
787 'env', 'NAS_DB=/nas', '/nas/bin/nas_server',
788 '-vdm', self.vdm_name,
789 '-detach', self.interface_name2,
790 ]
792 def cmd_get_interfaces(self):
793 return [
794 'env', 'NAS_DB=/nas', '/nas/bin/nas_server',
795 '-i',
796 '-vdm', self.vdm_name,
797 ]
799 def output_get_interfaces_vdm(self,
800 cifs_interface=FakeData.interface_name1,
801 nfs_interface=FakeData.interface_name2):
802 return (
803 """id = %(vdmid)s
804 name = %(name)s
805 acl = 0
806 type = vdm
807 server = server_2
808 rootfs = root_fs_vdm_vdm-fakeid
809 I18N mode = UNICODE
810 mountedfs =
811 member_of =
812 status :
813 defined = enabled
814 actual = loaded, active
815 Interfaces to services mapping:
816 interface=%(nfs_if_name)s :vdm
817 interface=%(cifs_if_name)s :cifs""" %
818 {'vdmid': self.vdm_id,
819 'name': self.vdm_name,
820 'nfs_if_name': nfs_interface,
821 'cifs_if_name': cifs_interface}
822 )
824 def output_get_interfaces_nfs(self,
825 cifs_interface=FakeData.interface_name1,
826 nfs_interface=FakeData.interface_name2):
827 return (
828 """id = %(vdmid)s
829 name = %(name)s
830 acl = 0
831 type = vdm
832 server = server_2
833 rootfs = root_fs_vdm_vdm-fakeid
834 I18N mode = UNICODE
835 mountedfs =
836 member_of =
837 status :
838 defined = enabled
839 actual = loaded, active
840 Interfaces to services mapping:
841 interface=%(nfs_if_name)s :nfs
842 interface=%(cifs_if_name)s :cifs""" %
843 {'vdmid': self.vdm_id,
844 'name': self.vdm_name,
845 'nfs_if_name': nfs_interface,
846 'cifs_if_name': cifs_interface}
847 )
850class PoolTestData(StorageObjectTestData):
851 def __init__(self):
852 super(PoolTestData, self).__init__()
854 @query
855 def req_get(self):
856 return (
857 '<StoragePoolQueryParams/>'
858 )
860 @response
861 def resp_get_succeed(self, name=None, id=None):
862 if not name:
863 name = self.pool_name
864 if not id:
865 id = self.pool_id
866 return (
867 '<QueryStatus maxSeverity="ok"/>'
868 '<StoragePool movers="1 2" memberVolumes="98" storageSystems="1" '
869 'name="fake" '
870 'description="Mapped Pool Pool_2 on APM00152904560" '
871 'mayContainSlicesDefault="true" diskType="Capacity" '
872 'size="511999" usedSize="20480" autoSize="511999" '
873 'virtualProvisioning="false" isHomogeneous="true" '
874 'dataServicePolicies="Thin=No,Compressed=No,Mirrored=No,Tiering '
875 'policy=Auto-Tier/Highest Available Tier" templatePool="59" '
876 'stripeCount="5" stripeSize="256" pool="9">'
877 '<SystemStoragePoolData dynamic="true" greedy="true" '
878 'potentialAdditionalSize="0" isBackendPool="true"/>'
879 '</StoragePool>'
880 '<StoragePool movers="1 2" memberVolumes="98" storageSystems="1" '
881 'name="%(name)s" '
882 'description="Mapped Pool Pool_2 on APM00152904560" '
883 'mayContainSlicesDefault="true" diskType="Capacity" '
884 'size="411999" usedSize="%(pool_used_size)s" '
885 'autoSize="%(pool_total_size)s" virtualProvisioning="false" '
886 'isHomogeneous="true" '
887 'dataServicePolicies="Thin=No,Compressed=No,Mirrored=No,Tiering '
888 'policy=Auto-Tier/Highest Available Tier" templatePool="59" '
889 'stripeCount="5" stripeSize="256" pool="%(id)s">'
890 '<SystemStoragePoolData dynamic="true" greedy="true" '
891 'potentialAdditionalSize="0" isBackendPool="true"/>'
892 '</StoragePool>' %
893 {'name': name,
894 'id': id,
895 'pool_used_size': self.pool_used_size,
896 'pool_total_size': self.pool_total_size}
897 )
900class MoverTestData(StorageObjectTestData):
901 def __init__(self):
902 super(MoverTestData, self).__init__()
904 @query
905 def req_get_ref(self):
906 return (
907 '<MoverQueryParams>'
908 '<AspectSelection movers="true"/>'
909 '</MoverQueryParams>'
910 )
912 @response
913 def resp_get_ref_succeed(self, name=None):
914 if not name:
915 name = self.mover_name
916 return (
917 '<QueryStatus maxSeverity="info">'
918 '<Problem messageCode="18522112101" facility="Generic" '
919 'component="API" message="The query may be incomplete or '
920 'requested object not found." severity="warning">'
921 '<Description>The query may be incomplete because some of the '
922 'Celerra components are unavailable or do not exist. Another '
923 'reason may be application error.</Description>'
924 '<Action>If the entire Celerra is functioning correctly, '
925 'check your client application logic.</Action>'
926 '<Diagnostics>Standby Data Mover server_2.faulted.server_3 is '
927 'out of service.</Diagnostics>'
928 '</Problem>'
929 '</QueryStatus>'
930 '<Mover name="%(name)s" host="1" role="primary" standbys="2" '
931 'i18NMode="UNICODE" failoverPolicy="auto" '
932 'ntpServers="192.168.1.82" mover="%(id)s"/>'
933 '<Mover name="server_3" host="2" role="standby" standbyFors="1" '
934 'i18NMode="ASCII" failoverPolicy="none" mover="2"/>' %
935 {'name': name, 'id': self.mover_id}
936 )
938 @query
939 def req_get(self):
940 return (
941 '<MoverQueryParams mover="%(id)s">'
942 '<AspectSelection moverInterfaces="true" moverStatuses="true" '
943 'movers="true" moverNisDomains="true" moverNetworkDevices="true" '
944 'moverDnsDomains="true" moverRoutes="true" '
945 'moverDeduplicationSettings="true"/>'
946 '</MoverQueryParams>' %
947 {'id': self.mover_id}
948 )
950 @response
951 def resp_get_succeed(self, name=None):
952 if not name: 952 ↛ 954line 952 didn't jump to line 954 because the condition on line 952 was always true
953 name = self.mover_name
954 return (
955 '<QueryStatus maxSeverity="ok"/><Mover name="%(name)s" '
956 'host="1" role="primary" i18NMode="UNICODE" failoverPolicy="none"'
957 ' ntpServers="192.168.1.82" mover="%(id)s"/>'
958 '<MoverStatus version="T8.1.3.34944" csTime="1406795150" '
959 'clock="140681" timezone="GMT-5" uptime="85096" '
960 'mover="%(id)s"><Status maxSeverity="ok"/>'
961 '</MoverStatus>'
962 '<MoverDnsDomain servers="192.168.1.82" protocol="udp" '
963 'mover="%(id)s" name="win2012.openstack"/>'
964 '<MoverInterface name="%(long_interface_name)s" device="mge0" '
965 'ipVersion="IPv4" netMask="255.255.255.0" '
966 'broadcastAddr="128.221.252.255" '
967 'macAddr="0:60:16:53:cc:87" mtu="1500" up="true" vlanid="0" '
968 'mover="%(id)s" ipAddress="128.221.252.1"/>'
969 '<MoverInterface name="%(interface_name1)s" device="cge-2-0" '
970 'ipVersion="IPv4" netMask="255.255.255.0" '
971 'broadcastAddr="128.221.252.255" macAddr="0:60:16:53:cc:87" '
972 'mtu="1500" up="true" vlanid="0" mover="%(id)s" '
973 'ipAddress="128.221.252.2"/>'
974 '<MoverInterface name="%(interface_name2)s" device="cge-2-1" '
975 'ipVersion="IPv4" netMask="255.255.255.0" '
976 'broadcastAddr="128.221.252.255" macAddr="0:60:16:53:cc:87" '
977 'mtu="1500" up="true" vlanid="0" mover="%(id)s" '
978 'ipAddress="128.221.252.3"/>'
979 '<MoverRoute destination="0.0.0.0" interface="192.168.1.178" '
980 'ipVersion="IPv4" netMask="0.0.0.0" '
981 'gateway="192.168.1.217" mover="%(id)s"/>'
982 '<LogicalNetworkDevice speed="auto" interfaces="192.168.1.136" '
983 'type="physical-ethernet" mover="%(id)s" name="cge-2-0"/>'
984 % {'id': self.mover_id,
985 'name': name,
986 'long_interface_name': self.long_interface_name[:31],
987 'interface_name1': self.interface_name1,
988 'interface_name2': self.interface_name2}
989 )
991 @start_task
992 def req_create_interface(self,
993 if_name=FakeData.interface_name1,
994 ip=FakeData.network_allocations_ip1):
995 return (
996 '<NewMoverInterface name="%(if_name)s" vlanid="%(vlan)s" '
997 'netMask="%(net_mask)s" device="%(device_name)s" '
998 'mover="%(mover_id)s" ipAddress="%(ip)s"/>'
999 % {'if_name': if_name,
1000 'vlan': self.vlan_id,
1001 'ip': ip,
1002 'mover_id': self.mover_id,
1003 'device_name': self.device_name,
1004 'net_mask': self.net_mask}
1005 )
1007 @start_task
1008 def req_create_interface_with_ipv6(self,
1009 if_name=FakeData.interface_name3,
1010 ip=FakeData.network_allocations_ip3):
1011 return (
1012 '<NewMoverInterface name="%(if_name)s" vlanid="%(vlan)s" '
1013 'ipVersion="IPv6" netMask="%(net_mask)s" '
1014 'device="%(device_name)s" '
1015 'mover="%(mover_id)s" ipAddress="%(ip)s"/>'
1016 % {'if_name': if_name,
1017 'vlan': self.vlan_id,
1018 'ip': ip,
1019 'mover_id': self.mover_id,
1020 'device_name': self.device_name,
1021 'net_mask': self.net_mask_v6}
1022 )
1024 @response
1025 def resp_create_interface_but_name_already_exist(self):
1026 return (
1027 '<Status maxSeverity="error">'
1028 '<Problem messageCode="13421840550" component="CS_CORE" '
1029 'message="%(interface_name)s : an entry with this name already '
1030 'exists" severity="error">'
1031 '<Description>Duplicate name specified</Description>'
1032 '<Action>Specify a unqiue name</Action>'
1033 '</Problem>'
1034 '</Status>' % {'interface_name': self.interface_name1}
1035 )
1037 @response
1038 def resp_create_interface_but_ip_already_exist(self):
1039 return (
1040 '<Status maxSeverity="error">'
1041 '<Problem messageCode="13691781136" component="CS_CORE" '
1042 'message="Interface %(ip)s already exists." severity="error">'
1043 '<Description></Description><Action></Action>'
1044 '</Problem>'
1045 '</Status>' % {'ip': self.ip_address1}
1046 )
1048 @response
1049 def resp_create_interface_with_conflicted_vlan_id(self):
1050 return (
1051 '<Status maxSeverity="error">'
1052 '<Problem messageCode="13421850371" component="CS_CORE" '
1053 'message="160: Invalid VLAN change. Other interfaces on this '
1054 'subnet are in a different VLAN." severity="error">'
1055 '<Description>The operation cannot complete because other '
1056 'interfaces on the same subnet are in a different VLAN. '
1057 'The Data Mover requires all interfaces in the same subnet '
1058 'to be in the same VLAN.</Description>'
1059 '<Action>Specify a VLAN to match other interfaces in the same '
1060 'subnet. To move multiple interfaces to a different VLAN, '
1061 'first set the VLAN id on each interface to 0, '
1062 'and then set their VLAN id\'s to the new VLAN number.</Action>'
1063 '</Problem>'
1064 '</Status>'
1065 )
1067 @start_task
1068 def req_delete_interface(self, ip=FakeData.network_allocations_ip1):
1070 return (
1071 '<DeleteMoverInterface mover="%(mover_id)s" '
1072 'ipAddress="%(ip)s"/>' %
1073 {'ip': ip,
1074 'mover_id': self.mover_id, }
1075 )
1077 @response
1078 def resp_delete_interface_but_nonexistent(self):
1079 return (
1080 '<Status maxSeverity="error">'
1081 '<Problem messageCode="13691781134" component="APL" '
1082 'message="Device 192.168.237.100 does not exist." '
1083 'severity="error">'
1084 '<Description></Description>'
1085 '<Action></Action>'
1086 '</Problem>'
1087 '</Status>'
1088 )
1090 def cmd_get_interconnect_id(self):
1091 return [
1092 'env', 'NAS_DB=/nas', '/nas/bin/nas_cel',
1093 '-interconnect', '-l',
1094 ]
1096 def output_get_interconnect_id(self):
1097 return (
1098 'id name source_server destination_system destination_server\n'
1099 '%(id)s loopback %(src_server)s nas149 %(dest_server)s\n' %
1100 {'id': self.interconnect_id,
1101 'src_server': self.mover_name,
1102 'dest_server': self.mover_name}
1103 )
1105 def cmd_get_physical_devices(self):
1106 return [
1107 'env', 'NAS_DB=/nas', '/nas/bin/server_sysconfig',
1108 self.mover_name, '-pci',
1109 ]
1111 def output_get_physical_devices(self):
1112 return (
1113 'server_2 : PCI DEVICES:\n'
1114 'On Board:\n'
1115 ' PMC QE8 Fibre Channel Controller\n'
1116 ' 0: fcp-0-0 IRQ: 20 addr: 5006016047a00245\n'
1117 ' 0: fcp-0-1 IRQ: 21 addr: 5006016147a00245\n'
1118 ' 0: fcp-0-2 IRQ: 22 addr: 5006016247a00245\n'
1119 ' 0: fcp-0-3 IRQ: 23 addr: 5006016347a00245\n'
1120 ' Broadcom Gigabit Ethernet Controller\n'
1121 ' 0: cge-1-0 IRQ: 24\n'
1122 ' speed=auto duplex=auto txflowctl=disable rxflowctl=disable\n'
1123 ' Link: Up\n'
1124 ' 0: cge-1-1 IRQ: 25\n'
1125 ' speed=auto duplex=auto txflowctl=disable rxflowctl=disable\n'
1126 ' Link: Down\n'
1127 ' 0: cge-1-2 IRQ: 26\n'
1128 ' speed=auto duplex=auto txflowctl=disable rxflowctl=disable\n'
1129 ' Link: Down\n'
1130 ' 0: cge-1-3 IRQ: 27\n'
1131 ' speed=auto duplex=auto txflowctl=disable rxflowctl=disable\n'
1132 ' Link: Up\n'
1133 'Slot: 4\n'
1134 ' PLX PCI-Express Switch Controller\n'
1135 ' 1: PLX PEX8648 IRQ: 10\n'
1136 )
1139class DNSDomainTestData(StorageObjectTestData):
1140 def __init__(self):
1141 super(DNSDomainTestData, self).__init__()
1143 @start_task
1144 def req_create(self, ip_addr=None):
1145 if ip_addr is None:
1146 ip_addr = self.dns_ip_address
1148 return (
1149 '<NewMoverDnsDomain mover="%(mover_id)s" protocol="udp" '
1150 'name="%(domain_name)s" servers="%(server_ips)s"/>' %
1151 {'mover_id': self.mover_id,
1152 'domain_name': self.domain_name,
1153 'server_ips': ip_addr}
1154 )
1156 @start_task
1157 def req_delete(self):
1158 return (
1159 '<DeleteMoverDnsDomain mover="%(mover_id)s" '
1160 'name="%(domain_name)s"/>' %
1161 {'mover_id': self.mover_id,
1162 'domain_name': self.domain_name}
1163 )
1166class CIFSServerTestData(StorageObjectTestData):
1167 def __init__(self):
1168 super(CIFSServerTestData, self).__init__()
1170 @start_task
1171 def req_create(self, mover_id, is_vdm=True, ip_addr=None):
1172 if ip_addr is None:
1173 ip_addr = self.ip_address1
1175 return (
1176 '<NewW2KCifsServer interfaces="%(ip)s" compName="%(comp_name)s" '
1177 'name="%(name)s" domain="%(domain)s">'
1178 '<MoverOrVdm mover="%(mover_id)s" moverIdIsVdm="%(is_vdm)s"/>'
1179 '<Aliases><li>%(alias)s</li></Aliases>'
1180 '<JoinDomain userName="%(domain_user)s" '
1181 'password="%(domain_password)s"/>'
1182 '</NewW2KCifsServer>'
1183 % {'ip': ip_addr,
1184 'comp_name': self.cifs_server_name,
1185 'name': self.cifs_server_name[-14:],
1186 'mover_id': mover_id,
1187 'alias': self.cifs_server_name[-12:],
1188 'domain_user': self.domain_user,
1189 'domain_password': self.domain_password,
1190 'domain': self.domain_name,
1191 'is_vdm': 'true' if is_vdm else 'false'}
1192 )
1194 @query
1195 def req_get(self, mover_id, is_vdm=True):
1196 return (
1197 '<CifsServerQueryParams>'
1198 '<MoverOrVdm mover="%(mover_id)s" moverIdIsVdm="%(is_vdm)s"/>'
1199 '</CifsServerQueryParams>' %
1200 {'mover_id': mover_id,
1201 'is_vdm': 'true' if is_vdm else 'false'}
1202 )
1204 @response
1205 def resp_get_succeed(self, mover_id, is_vdm, join_domain,
1206 cifs_server_name=None,
1207 ip_addr=None):
1208 if cifs_server_name is None:
1209 cifs_server_name = self.cifs_server_name
1211 if ip_addr is None:
1212 ip_addr = self.ip_address1
1214 return (
1215 '<QueryStatus maxSeverity="ok"/>'
1216 '<CifsServer interfaces="%(ip)s" type="W2K" '
1217 'localUsers="false" name="%(cifsserver)s" '
1218 'mover="%(mover_id)s" moverIdIsVdm="%(is_vdm)s"><Aliases>'
1219 '<li>%(alias)s</li></Aliases><W2KServerData domain='
1220 '"%(domain)s" compName="%(comp_name)s" '
1221 'domainJoined="%(join_domain)s"/></CifsServer>'
1222 % {'mover_id': mover_id,
1223 'cifsserver': self.cifs_server_name[-14:],
1224 'ip': ip_addr,
1225 'is_vdm': 'true' if is_vdm else 'false',
1226 'alias': self.cifs_server_name[-12:],
1227 'domain': self.domain_name,
1228 'join_domain': 'true' if join_domain else 'false',
1229 'comp_name': cifs_server_name}
1230 )
1232 @response
1233 def resp_get_without_interface(self, mover_id, is_vdm, join_domain):
1234 return (
1235 '<QueryStatus maxSeverity="ok"/>'
1236 '<CifsServer interfaces="" type="W2K" localUsers="false" '
1237 'name="%(cifsserver)s" mover="%(mover_id)s" '
1238 'moverIdIsVdm="%(is_vdm)s">'
1239 '<Aliases><li>%(alias)s</li></Aliases>'
1240 '<W2KServerData domain="%(domain)s" compName="%(comp_name)s" '
1241 'domainJoined="%(join_domain)s"/></CifsServer>'
1242 % {'mover_id': mover_id,
1243 'cifsserver': self.cifs_server_name[-14:],
1244 'is_vdm': 'true' if is_vdm else 'false',
1245 'alias': self.cifs_server_name[-12:],
1246 'domain': self.domain_name,
1247 'join_domain': 'true' if join_domain else 'false',
1248 'comp_name': self.cifs_server_name}
1249 )
1251 @start_task
1252 def req_modify(self, mover_id, is_vdm=True, join_domain=False):
1253 return (
1254 '<ModifyW2KCifsServer mover="%(mover_id)s" '
1255 'moverIdIsVdm="%(is_vdm)s" name="%(cifsserver)s">'
1256 '<DomainSetting userName="%(username)s" password="%(pw)s" '
1257 'joinDomain="%(join_domain)s"/>'
1258 '</ModifyW2KCifsServer>'
1259 % {'mover_id': mover_id,
1260 'is_vdm': 'true' if is_vdm else 'false',
1261 'join_domain': 'true' if join_domain else 'false',
1262 'cifsserver': self.cifs_server_name[-14:],
1263 'username': self.domain_user,
1264 'pw': self.domain_password}
1265 )
1267 @response
1268 def resp_modify_but_already_join_domain(self):
1269 return (
1270 '<Status maxSeverity="error"> '
1271 '<Problem messageCode="13157007726" component="DART" '
1272 'message="Fake message." severity="error">'
1273 '<Description>Fake description</Description>'
1274 '<Action>Fake action.</Action>'
1275 '</Problem>'
1276 '</Status> '
1277 )
1279 @response
1280 def resp_modify_but_unjoin_domain(self):
1281 return (
1282 '<Status maxSeverity="error"> '
1283 '<Problem messageCode="13157007723" component="DART" '
1284 'message="Fake message." severity="error">'
1285 '<Description>Fake description</Description>'
1286 '<Action>Fake action.</Action>'
1287 '</Problem>'
1288 '</Status> '
1289 )
1291 @start_task
1292 def req_delete(self, mover_id, is_vdm=True):
1293 return (
1294 '<DeleteCifsServer mover="%(mover_id)s" moverIdIsVdm="%(is_vdm)s" '
1295 'name="%(cifsserver)s"/>'
1296 % {'mover_id': mover_id,
1297 'is_vdm': 'true' if is_vdm else 'false',
1298 'cifsserver': self.cifs_server_name[-14:]}
1299 )
1302class CIFSShareTestData(StorageObjectTestData):
1303 def __init__(self):
1304 super(CIFSShareTestData, self).__init__()
1306 @start_task
1307 def req_create(self, mover_id, is_vdm=True):
1308 return (
1309 '<NewCifsShare path="%(path)s" name="%(share_name)s">'
1310 '<MoverOrVdm mover="%(mover_id)s" moverIdIsVdm="%(is_vdm)s"/>'
1311 '<CifsServers><li>%(cifsserver)s</li></CifsServers>'
1312 '</NewCifsShare>' %
1313 {'path': '/' + self.share_name,
1314 'share_name': self.share_name,
1315 'mover_id': mover_id,
1316 'is_vdm': 'true' if is_vdm else 'false',
1317 'cifsserver': self.cifs_server_name[-14:]}
1318 )
1320 @start_task
1321 def req_delete(self, mover_id, is_vdm=True):
1322 return (
1323 '<DeleteCifsShare mover="%(mover_id)s" moverIdIsVdm="%(is_vdm)s" '
1324 'name="%(share_name)s">'
1325 '<CifsServers><li>%(cifsserver)s</li></CifsServers>'
1326 '</DeleteCifsShare>' %
1327 {'share_name': self.share_name,
1328 'mover_id': mover_id,
1329 'is_vdm': 'true' if is_vdm else 'false',
1330 'cifsserver': self.cifs_server_name[-12:]}
1331 )
1333 @query
1334 def req_get(self):
1335 return '<CifsShareQueryParams name="%s"/>' % self.share_name
1337 @response
1338 def resp_get_succeed(self, mover_id, is_vdm=True):
1339 return (
1340 '<QueryStatus maxSeverity="ok"/>'
1341 '<CifsShare path="%(path)s" fileSystem="%(fsid)s" name="%(name)s" '
1342 'mover="%(moverid)s" moverIdIsVdm="%(is_vdm)s">'
1343 '<CifsServers><li>%(alias)s</li>'
1344 '</CifsServers>'
1345 '</CifsShare>' %
1346 {'path': self.path,
1347 'fsid': self.filesystem_id,
1348 'name': self.share_name,
1349 'moverid': mover_id,
1350 'is_vdm': 'true' if is_vdm else 'false',
1351 'alias': self.cifs_server_name[-12:]}
1352 )
1354 def cmd_disable_access(self):
1355 cmd_str = 'sharesd %s set noaccess' % self.share_name
1356 return [
1357 'env', 'NAS_DB=/nas',
1358 '/nas/bin/.server_config', self.vdm_name,
1359 '-v', '%s' % cmd_str,
1360 ]
1362 def cmd_change_access(self, access_level=const.ACCESS_LEVEL_RW,
1363 action='grant', user=None):
1364 if user is None:
1365 user = self.domain_user
1366 account = user + '@' + self.domain_name
1368 if access_level == const.ACCESS_LEVEL_RW:
1369 str_access = 'fullcontrol'
1370 else:
1371 str_access = 'read'
1373 allow_str = (
1374 'sharesd %(share_name)s %(action)s %(account)s=%(access)s'
1375 % {'share_name': self.share_name,
1376 'action': action,
1377 'account': account,
1378 'access': str_access}
1379 )
1380 return [
1381 'env', 'NAS_DB=/nas',
1382 '/nas/bin/.server_config', self.vdm_name,
1383 '-v', '%s' % allow_str,
1384 ]
1386 def cmd_get_access(self):
1387 get_str = 'sharesd %s dump' % self.share_name
1388 return [
1389 'env', 'NAS_DB=/nas',
1390 '/nas/bin/.server_config', self.vdm_name,
1391 '-v', '%s' % get_str,
1392 ]
1394 def output_allow_access(self):
1395 return (
1396 "Command succeeded: :3 sharesd %(share)s grant "
1397 "%(user)s@%(domain)s=fullcontrol"
1398 % {'share': self.share_name,
1399 'user': self.domain_user,
1400 'domain': self.domain_name}
1401 )
1403 def output_allow_access_but_duplicate_ace(self):
1404 return (
1405 '%(vdm_name)s : commands processed: 1'
1406 'output is complete'
1407 '1443422844: SMB: 6: ACE for %(domain)s\\%(user)s '
1408 'unchanged'
1409 '1443422844: ADMIN: 3: '
1410 'Command failed: :23 '
1411 'sharesd %(share)s grant %(user)s@%(domain)s=read'
1412 'Error 4020: %(vdm_name)s : failed to complete command"'
1413 % {'share': self.share_name,
1414 'user': self.domain_user,
1415 'domain': self.domain_name,
1416 'vdm_name': self.vdm_name}
1417 )
1419 def output_deny_access_but_no_ace(self):
1420 return (
1421 '%(vdm_name)s : commands processed: 1'
1422 'output is complete'
1423 '1443515516: SMB: 6: No ACE found for %(domain)s\\%(user)s '
1424 '1443515516: ADMIN: 3: '
1425 'Command failed: :26 '
1426 'sharesd %(share)s revoke %(user)s@%(domain)s=read'
1427 'Error 4020: %(vdm_name)s : failed to complete command"'
1428 % {'share': self.share_name,
1429 'user': self.domain_user,
1430 'domain': self.domain_name,
1431 'vdm_name': self.vdm_name}
1432 )
1434 def output_deny_access_but_no_user_found(self):
1435 return (
1436 '%(vdm_name)s : commands processed: 1'
1437 'output is complete'
1438 '1443520322: SMB: 6: Cannot get mapping for %(domain)s\\%(user)s '
1439 '1443520322: ADMIN: 3: '
1440 'Command failed: :26 '
1441 'sharesd %(share)s revoke %(user)s@%(domain)s=read'
1442 'Error 4020: %(vdm_name)s : failed to complete command"'
1443 % {'share': self.share_name,
1444 'user': self.domain_user,
1445 'domain': self.domain_name,
1446 'vdm_name': self.vdm_name}
1447 )
1450class NFSShareTestData(StorageObjectTestData):
1451 def __init__(self):
1452 super(NFSShareTestData, self).__init__()
1454 def cmd_create(self):
1455 default_access = 'access=-0.0.0.0/0.0.0.0'
1456 return [
1457 'env', 'NAS_DB=/nas', '/nas/bin/server_export', self.vdm_name,
1458 '-option', default_access,
1459 self.path,
1460 ]
1462 def output_create(self):
1463 return "%s : done" % self.vdm_name
1465 def cmd_get(self):
1466 return [
1467 'env', 'NAS_DB=/nas', '/nas/bin/server_export', self.vdm_name,
1468 '-P', 'nfs',
1469 '-list', self.path,
1470 ]
1472 def output_get_succeed(self, rw_hosts, ro_hosts):
1473 rw_hosts = [utils.convert_ipv6_format_if_needed(ip_addr) for ip_addr in
1474 rw_hosts]
1475 ro_hosts = [utils.convert_ipv6_format_if_needed(ip_addr) for ip_addr in
1476 ro_hosts]
1478 if rw_hosts and ro_hosts:
1479 return (
1480 '%(mover_name)s :\nexport "%(path)s" '
1481 'access=%(host)s:-0.0.0.0/0.0.0.0 root=%(host)s '
1482 'rw=%(rw_host)s ro=%(ro_host)s\n'
1483 % {'mover_name': self.vdm_name,
1484 'path': self.path,
1485 'host': ":".join(rw_hosts + ro_hosts),
1486 'rw_host': ":".join(rw_hosts),
1487 'ro_host': ":".join(ro_hosts)}
1488 )
1489 elif rw_hosts: 1489 ↛ 1499line 1489 didn't jump to line 1499 because the condition on line 1489 was always true
1490 return (
1491 '%(mover_name)s :\nexport "%(path)s" '
1492 'access=%(host)s:-0.0.0.0/0.0.0.0 root=%(host)s '
1493 'rw=%(rw_host)s\n'
1494 % {'mover_name': self.vdm_name,
1495 'host': ":".join(rw_hosts),
1496 'path': self.path,
1497 'rw_host': ":".join(rw_hosts)}
1498 )
1499 elif ro_hosts:
1500 return (
1501 '%(mover_name)s :\nexport "%(path)s" '
1502 'access=%(host)s:-0.0.0.0/0.0.0.0 root=%(host)s '
1503 'ro=%(ro_host)s\n'
1504 % {'mover_name': self.vdm_name,
1505 'host': ":".join(ro_hosts),
1506 'path': self.path,
1507 'ro_host': ":".join(ro_hosts)}
1508 )
1509 else:
1510 return (
1511 '%(mover_name)s :\nexport "%(path)s" '
1512 'access=-0.0.0.0/0.0.0.0\n'
1513 % {'mover_name': self.vdm_name,
1514 'path': self.path}
1515 )
1517 def output_get_but_not_found(self):
1518 return (
1519 '%(mover_name)s : \nError 2: %(mover_name)s : '
1520 'No such file or directory \n' % {'mover_name': self.vdm_name}
1521 )
1523 def cmd_delete(self):
1524 return [
1525 'env', 'NAS_DB=/nas', '/nas/bin/server_export', self.vdm_name,
1526 '-unexport',
1527 '-perm',
1528 self.path,
1529 ]
1531 def output_delete_succeed(self):
1532 return "%s : done" % self.vdm_name
1534 def output_delete_but_locked(self):
1535 return ("Error 2201: %s : unable to acquire lock(s), try later"
1536 % self.vdm_name)
1538 def cmd_set_access(self, rw_hosts, ro_hosts):
1539 rw_hosts = [utils.convert_ipv6_format_if_needed(ip_addr) for ip_addr in
1540 rw_hosts]
1541 ro_hosts = [utils.convert_ipv6_format_if_needed(ip_addr) for ip_addr in
1542 ro_hosts]
1544 access_str = ("access=%(access_hosts)s:-0.0.0.0/0.0.0.0,"
1545 "root=%(root_hosts)s,rw=%(rw_hosts)s,ro=%(ro_hosts)s" %
1546 {'rw_hosts': ":".join(rw_hosts),
1547 'ro_hosts': ":".join(ro_hosts),
1548 'root_hosts': ":".join(rw_hosts + ro_hosts),
1549 'access_hosts': ":".join(rw_hosts + ro_hosts)})
1551 return [
1552 'env', 'NAS_DB=/nas', '/nas/bin/server_export', self.vdm_name,
1553 '-ignore',
1554 '-option', access_str,
1555 self.path,
1556 ]
1558 def output_set_access_success(self):
1559 return "%s : done" % self.vdm_name
1562class FakeEMCShareDriver(object):
1563 def __init__(self, enas_type='vnx'):
1564 self.configuration = conf.Configuration(None)
1565 self.configuration.append_config_values = mock.Mock(return_value=0)
1566 self.configuration.emc_share_backend = FakeData.emc_share_backend
1567 self.configuration.vnx_server_container = FakeData.mover_name
1568 if enas_type == 'powermax':
1569 self.configuration.emc_share_backend = (
1570 FakeData.powermax_share_backend)
1571 self.configuration.vmax_server_container = FakeData.mover_name
1572 self.configuration.emc_nas_server = FakeData.emc_nas_server
1573 self.configuration.emc_nas_login = FakeData.emc_nas_login
1574 self.configuration.emc_nas_password = FakeData.emc_nas_password
1575 self.configuration.share_backend_name = FakeData.share_backend_name
1578CIFS_SHARE = fake_share.fake_share(
1579 id=FakeData.share_id,
1580 name=FakeData.share_name,
1581 size=FakeData.share_size,
1582 share_network_id=FakeData.share_network_id,
1583 share_server_id=FakeData.share_server_id,
1584 host=FakeData.host,
1585 share_proto='CIFS')
1587NFS_SHARE = fake_share.fake_share(
1588 id=FakeData.share_id,
1589 name=FakeData.share_name,
1590 size=FakeData.share_size,
1591 share_network_id=FakeData.share_network_id,
1592 share_server_id=FakeData.share_server_id,
1593 host=FakeData.host,
1594 share_proto='NFS')
1596CIFS_RW_ACCESS = fake_share.fake_access(
1597 access_type='user',
1598 access_to=FakeData.domain_user,
1599 access_level='rw')
1601CIFS_RO_ACCESS = fake_share.fake_access(
1602 access_type='user',
1603 access_to=FakeData.domain_user,
1604 access_level='ro')
1606NFS_RW_ACCESS = fake_share.fake_access(
1607 access_type='ip',
1608 access_to=FakeData.nfs_host_ip,
1609 access_level='rw')
1611NFS_RW_ACCESS_IPV6 = fake_share.fake_access(
1612 access_type='ip',
1613 access_to=FakeData.nfs_host_ipv6,
1614 access_level='rw')
1616NFS_RO_ACCESS = fake_share.fake_access(
1617 access_type='ip',
1618 access_to=FakeData.nfs_host_ip,
1619 access_level='ro')
1621NFS_RO_ACCESS_IPV6 = fake_share.fake_access(
1622 access_type='ip',
1623 access_to=FakeData.nfs_host_ipv6,
1624 access_level='ro')
1626SHARE_SERVER = {
1627 'id': FakeData.share_server_id,
1628 'share_network': {
1629 'name': 'fake_share_network',
1630 'id': FakeData.share_network_id
1631 },
1632 'share_network_id': FakeData.share_network_id,
1633 'backend_details': {
1634 'share_server_name': FakeData.vdm_name,
1635 'cifs_if': FakeData.network_allocations_ip1,
1636 'nfs_if': FakeData.network_allocations_ip2,
1637 }
1638}
1640SHARE_SERVER_IPV6 = {
1641 'id': FakeData.share_server_id,
1642 'share_network': {
1643 'name': 'fake_share_network',
1644 'id': FakeData.share_network_id
1645 },
1646 'share_network_id': FakeData.share_network_id,
1647 'backend_details': {
1648 'share_server_name': FakeData.vdm_name,
1649 'cifs_if': FakeData.network_allocations_ip3,
1650 'nfs_if': FakeData.network_allocations_ip4,
1651 }
1652}
1654SERVER_DETAIL = {
1655 'share_server_name': FakeData.vdm_name,
1656 'cifs_if': FakeData.network_allocations_ip1,
1657 'nfs_if': FakeData.network_allocations_ip2,
1658}
1660SERVER_DETAIL_IPV6 = {
1661 'share_server_name': FakeData.vdm_name,
1662 'cifs_if': FakeData.network_allocations_ip3,
1663 'nfs_if': FakeData.network_allocations_ip4,
1664}
1666SECURITY_SERVICE = [
1667 {
1668 'type': 'active_directory',
1669 'domain': FakeData.domain_name,
1670 'dns_ip': FakeData.dns_ip_address,
1671 'user': FakeData.domain_user,
1672 'password': FakeData.domain_password
1673 },
1674]
1676SECURITY_SERVICE_IPV6 = [
1677 {
1678 'type': 'active_directory',
1679 'domain': FakeData.domain_name,
1680 'dns_ip': FakeData.dns_ipv6_address,
1681 'user': FakeData.domain_user,
1682 'password': FakeData.domain_password
1683 },
1684]
1686NETWORK_INFO = {
1687 'server_id': FakeData.share_server_id,
1688 'cidr': FakeData.cidr,
1689 'security_services': [
1690 {'type': 'active_directory',
1691 'domain': FakeData.domain_name,
1692 'dns_ip': FakeData.dns_ip_address,
1693 'user': FakeData.domain_user,
1694 'password': FakeData.domain_password},
1695 ],
1696 'segmentation_id': FakeData.segmentation_id,
1697 'network_type': 'vlan',
1698 'network_allocations': [
1699 {'id': FakeData.network_allocations_id1,
1700 'ip_address': FakeData.network_allocations_ip1,
1701 'ip_version': FakeData.network_allocations_ip_version1},
1702 {'id': FakeData.network_allocations_id2,
1703 'ip_address': FakeData.network_allocations_ip2,
1704 'ip_version': FakeData.network_allocations_ip_version2}
1705 ]
1706}
1708NETWORK_INFO_IPV6 = {
1709 'server_id': FakeData.share_server_id,
1710 'cidr': FakeData.cidr_v6,
1711 'security_services': [
1712 {'type': 'active_directory',
1713 'domain': FakeData.domain_name,
1714 'dns_ip': FakeData.dns_ipv6_address,
1715 'user': FakeData.domain_user,
1716 'password': FakeData.domain_password},
1717 ],
1718 'segmentation_id': FakeData.segmentation_id,
1719 'network_type': 'vlan',
1720 'network_allocations': [
1721 {'id': FakeData.network_allocations_id3,
1722 'ip_address': FakeData.network_allocations_ip3,
1723 'ip_version': FakeData.network_allocations_ip_version3},
1724 {'id': FakeData.network_allocations_id4,
1725 'ip_address': FakeData.network_allocations_ip4,
1726 'ip_version': FakeData.network_allocations_ip_version4}
1727 ]
1728}
1730STATS = dict(
1731 share_backend_name='VNX',
1732 vendor_name='EMC',
1733 storage_protocol='NFS_CIFS',
1734 driver_version='2.0.0,')