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

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. 

15 

16from unittest import mock 

17 

18from oslo_utils import units 

19 

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 

24 

25 

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 ) 

35 

36 return inner 

37 

38 

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>') 

47 

48 return inner 

49 

50 

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() 

60 

61 return inner 

62 

63 

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' 

72 

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 

78 

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' 

92 

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' 

102 

103 # Share server information 

104 share_server_id = '56aafd02-4d44-43d7-b784-57fc88167224' 

105 

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 

111 

112 # Mountpoint information 

113 path = '/' + share_name 

114 

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' 

127 

128 # VDM information 

129 vdm_name = share_server_id 

130 vdm_id = 'fake_vdm_id' 

131 

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 

137 

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' 

145 

146 fake_output = '' 

147 

148 fake_error_msg = 'fake error message' 

149 

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' 

156 

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 """ 

165 

166 

167class StorageObjectTestData(object): 

168 def __init__(self): 

169 self.share_name = FakeData.share_name 

170 

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 

175 

176 self.path = FakeData.path 

177 

178 self.snapshot_name = FakeData.snapshot_name 

179 self.snapshot_id = FakeData.snapshot_id 

180 self.snapshot_size = 10 * units.Ki 

181 

182 self.src_snap_name = FakeData.src_snap_name 

183 self.src_fileystems_name = FakeData.src_share_name 

184 

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 

189 

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 

194 

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 

207 

208 self.cifs_server_name = FakeData.vdm_name 

209 

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 

214 

215 self.device_name = FakeData.device_name 

216 

217 self.interconnect_id = FakeData.interconnect_id 

218 

219 self.rw_hosts = FakeData.rw_hosts 

220 self.ro_hosts = FakeData.ro_hosts 

221 self.nfs_host_ip = FakeData.nfs_host_ip 

222 

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 

226 

227 self.fake_output = FakeData.fake_output 

228 

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 ) 

247 

248 @response 

249 def resp_get_without_value(self): 

250 return ( 

251 '<QueryStatus maxSeverity="ok"/>' 

252 ) 

253 

254 @response 

255 def resp_task_succeed(self): 

256 return ( 

257 '<TaskResponse taskId="123">' 

258 '<Status maxSeverity="ok"/>' 

259 '</TaskResponse>' 

260 ) 

261 

262 @response 

263 def resp_task_error(self): 

264 return ( 

265 '<TaskResponse taskId="123">' 

266 '<Status maxSeverity="error"/>' 

267 '</TaskResponse>' 

268 ) 

269 

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 ) 

287 

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>') 

298 

299 @start_task 

300 def req_fake_start_task(self): 

301 return '<StartFake name="foo"></StartFake>' 

302 

303 

304class FileSystemTestData(StorageObjectTestData): 

305 def __init__(self): 

306 super(FileSystemTestData, self).__init__() 

307 

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 ) 

321 

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 ) 

335 

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 ) 

350 

351 @start_task 

352 def req_delete(self): 

353 return ( 

354 '<DeleteFileSystem fileSystem="%(id)s"/>' % 

355 {'id': self.filesystem_id} 

356 ) 

357 

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 ) 

375 

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 ) 

386 

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 ) 

399 

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 ) 

410 

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 ) 

429 

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 ) 

447 

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 ) 

474 

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 ] 

488 

489 def cmd_copy_ckpt(self): 

490 session_name = self.filesystem_name + ':' + self.src_snap_name 

491 

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 ] 

501 

502 output_copy_ckpt = "OK" 

503 error_copy_ckpt = "ERROR" 

504 

505 def cmd_nas_fs_info(self): 

506 return [ 

507 'env', 'NAS_DB=/nas', '/nas/bin/nas_fs', 

508 '-info', self.filesystem_name, 

509 ] 

510 

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}) 

531 

532 def cmd_delete(self): 

533 return [ 

534 'env', 'NAS_DB=/nas', '/nas/bin/nas_fs', 

535 '-delete', self.snapshot_name, 

536 '-Force', 

537 ] 

538 

539 

540class SnapshotTestData(StorageObjectTestData): 

541 def __init__(self): 

542 super(SnapshotTestData, self).__init__() 

543 

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 ) 

555 

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 ) 

569 

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 ) 

581 

582 @query 

583 def req_get(self): 

584 return ( 

585 '<CheckpointQueryParams><Alias name="%(name)s"/>' 

586 '</CheckpointQueryParams>' 

587 % {'name': self.snapshot_name} 

588 ) 

589 

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 ) 

601 

602 @start_task 

603 def req_delete(self): 

604 return ( 

605 '<DeleteCheckpoint checkpoint="%(id)s"/>' % 

606 {'id': self.snapshot_id} 

607 ) 

608 

609 

610class MountPointTestData(StorageObjectTestData): 

611 def __init__(self): 

612 super(MountPointTestData, self).__init__() 

613 

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 ) 

625 

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> ') 

637 

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 ) 

647 

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 ) 

660 

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 ) 

669 

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 ) 

688 

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 ] 

696 

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 ] 

702 

703 

704class VDMTestData(StorageObjectTestData): 

705 def __init__(self): 

706 super(VDMTestData, self).__init__() 

707 

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 ) 

714 

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 ) 

735 

736 @query 

737 def req_get(self): 

738 return '<VdmQueryParams/>' 

739 

740 @response 

741 def resp_get_succeed(self, name=None, interface1=None, interface2=None): 

742 if name is None: 

743 name = self.vdm_name 

744 

745 if interface1 is None: 

746 interface1 = self.interface_name1 

747 

748 if interface2 is None: 

749 interface2 = self.interface_name2 

750 

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 ) 

764 

765 @response 

766 def resp_get_but_not_found(self): 

767 return ( 

768 '<QueryStatus maxSeverity="ok"/>' 

769 ) 

770 

771 @start_task 

772 def req_delete(self): 

773 return '<DeleteVdm vdm="%(vdmid)s"/>' % {'vdmid': self.vdm_id} 

774 

775 def cmd_attach_nfs_interface(self, interface=None): 

776 if interface is None: 

777 interface = self.interface_name2 

778 

779 return [ 

780 'env', 'NAS_DB=/nas', '/nas/bin/nas_server', 

781 '-vdm', self.vdm_name, 

782 '-attach', interface, 

783 ] 

784 

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 ] 

791 

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 ] 

798 

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 ) 

823 

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 ) 

848 

849 

850class PoolTestData(StorageObjectTestData): 

851 def __init__(self): 

852 super(PoolTestData, self).__init__() 

853 

854 @query 

855 def req_get(self): 

856 return ( 

857 '<StoragePoolQueryParams/>' 

858 ) 

859 

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 ) 

898 

899 

900class MoverTestData(StorageObjectTestData): 

901 def __init__(self): 

902 super(MoverTestData, self).__init__() 

903 

904 @query 

905 def req_get_ref(self): 

906 return ( 

907 '<MoverQueryParams>' 

908 '<AspectSelection movers="true"/>' 

909 '</MoverQueryParams>' 

910 ) 

911 

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 ) 

937 

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 ) 

949 

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 ) 

990 

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 ) 

1006 

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 ) 

1023 

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 ) 

1036 

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 ) 

1047 

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 ) 

1066 

1067 @start_task 

1068 def req_delete_interface(self, ip=FakeData.network_allocations_ip1): 

1069 

1070 return ( 

1071 '<DeleteMoverInterface mover="%(mover_id)s" ' 

1072 'ipAddress="%(ip)s"/>' % 

1073 {'ip': ip, 

1074 'mover_id': self.mover_id, } 

1075 ) 

1076 

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 ) 

1089 

1090 def cmd_get_interconnect_id(self): 

1091 return [ 

1092 'env', 'NAS_DB=/nas', '/nas/bin/nas_cel', 

1093 '-interconnect', '-l', 

1094 ] 

1095 

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 ) 

1104 

1105 def cmd_get_physical_devices(self): 

1106 return [ 

1107 'env', 'NAS_DB=/nas', '/nas/bin/server_sysconfig', 

1108 self.mover_name, '-pci', 

1109 ] 

1110 

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 ) 

1137 

1138 

1139class DNSDomainTestData(StorageObjectTestData): 

1140 def __init__(self): 

1141 super(DNSDomainTestData, self).__init__() 

1142 

1143 @start_task 

1144 def req_create(self, ip_addr=None): 

1145 if ip_addr is None: 

1146 ip_addr = self.dns_ip_address 

1147 

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 ) 

1155 

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 ) 

1164 

1165 

1166class CIFSServerTestData(StorageObjectTestData): 

1167 def __init__(self): 

1168 super(CIFSServerTestData, self).__init__() 

1169 

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 

1174 

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 ) 

1193 

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 ) 

1203 

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 

1210 

1211 if ip_addr is None: 

1212 ip_addr = self.ip_address1 

1213 

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 ) 

1231 

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 ) 

1250 

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 ) 

1266 

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 ) 

1278 

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 ) 

1290 

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 ) 

1300 

1301 

1302class CIFSShareTestData(StorageObjectTestData): 

1303 def __init__(self): 

1304 super(CIFSShareTestData, self).__init__() 

1305 

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 ) 

1319 

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 ) 

1332 

1333 @query 

1334 def req_get(self): 

1335 return '<CifsShareQueryParams name="%s"/>' % self.share_name 

1336 

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 ) 

1353 

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 ] 

1361 

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 

1367 

1368 if access_level == const.ACCESS_LEVEL_RW: 

1369 str_access = 'fullcontrol' 

1370 else: 

1371 str_access = 'read' 

1372 

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 ] 

1385 

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 ] 

1393 

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 ) 

1402 

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 ) 

1418 

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 ) 

1433 

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 ) 

1448 

1449 

1450class NFSShareTestData(StorageObjectTestData): 

1451 def __init__(self): 

1452 super(NFSShareTestData, self).__init__() 

1453 

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 ] 

1461 

1462 def output_create(self): 

1463 return "%s : done" % self.vdm_name 

1464 

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 ] 

1471 

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] 

1477 

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 ) 

1516 

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 ) 

1522 

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 ] 

1530 

1531 def output_delete_succeed(self): 

1532 return "%s : done" % self.vdm_name 

1533 

1534 def output_delete_but_locked(self): 

1535 return ("Error 2201: %s : unable to acquire lock(s), try later" 

1536 % self.vdm_name) 

1537 

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] 

1543 

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)}) 

1550 

1551 return [ 

1552 'env', 'NAS_DB=/nas', '/nas/bin/server_export', self.vdm_name, 

1553 '-ignore', 

1554 '-option', access_str, 

1555 self.path, 

1556 ] 

1557 

1558 def output_set_access_success(self): 

1559 return "%s : done" % self.vdm_name 

1560 

1561 

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 

1576 

1577 

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') 

1586 

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') 

1595 

1596CIFS_RW_ACCESS = fake_share.fake_access( 

1597 access_type='user', 

1598 access_to=FakeData.domain_user, 

1599 access_level='rw') 

1600 

1601CIFS_RO_ACCESS = fake_share.fake_access( 

1602 access_type='user', 

1603 access_to=FakeData.domain_user, 

1604 access_level='ro') 

1605 

1606NFS_RW_ACCESS = fake_share.fake_access( 

1607 access_type='ip', 

1608 access_to=FakeData.nfs_host_ip, 

1609 access_level='rw') 

1610 

1611NFS_RW_ACCESS_IPV6 = fake_share.fake_access( 

1612 access_type='ip', 

1613 access_to=FakeData.nfs_host_ipv6, 

1614 access_level='rw') 

1615 

1616NFS_RO_ACCESS = fake_share.fake_access( 

1617 access_type='ip', 

1618 access_to=FakeData.nfs_host_ip, 

1619 access_level='ro') 

1620 

1621NFS_RO_ACCESS_IPV6 = fake_share.fake_access( 

1622 access_type='ip', 

1623 access_to=FakeData.nfs_host_ipv6, 

1624 access_level='ro') 

1625 

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} 

1639 

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} 

1653 

1654SERVER_DETAIL = { 

1655 'share_server_name': FakeData.vdm_name, 

1656 'cifs_if': FakeData.network_allocations_ip1, 

1657 'nfs_if': FakeData.network_allocations_ip2, 

1658} 

1659 

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} 

1665 

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] 

1675 

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] 

1685 

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} 

1707 

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} 

1729 

1730STATS = dict( 

1731 share_backend_name='VNX', 

1732 vendor_name='EMC', 

1733 storage_protocol='NFS_CIFS', 

1734 driver_version='2.0.0,')