Coverage for manila/tests/share/drivers/netapp/dataontap/cluster_mode/test_data_motion.py: 100%

580 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2026-02-18 22:19 +0000

1# Copyright (c) 2015 Alex Meade. All rights reserved. 

2# 

3# Licensed under the Apache License, Version 2.0 (the "License"); you may 

4# not use this file except in compliance with the License. You may obtain 

5# a copy of the License at 

6# 

7# http://www.apache.org/licenses/LICENSE-2.0 

8# 

9# Unless required by applicable law or agreed to in writing, software 

10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 

11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 

12# License for the specific language governing permissions and limitations 

13# under the License. 

14 

15import copy 

16import time 

17from unittest import mock 

18 

19import ddt 

20from oslo_config import cfg 

21 

22from manila import exception 

23from manila.share import configuration 

24from manila.share import driver 

25from manila.share.drivers.netapp.dataontap.client import api as netapp_api 

26from manila.share.drivers.netapp.dataontap.client import client_cmode 

27from manila.share.drivers.netapp.dataontap.cluster_mode import data_motion 

28from manila.share.drivers.netapp import options as na_opts 

29from manila.share.drivers.netapp import utils as na_utils 

30from manila.share import utils as share_utils 

31from manila import test 

32from manila.tests.share.drivers.netapp.dataontap import fakes as fake 

33from manila.tests.share.drivers.netapp import fakes as na_fakes 

34 

35 

36CONF = cfg.CONF 

37 

38 

39@ddt.ddt 

40class NetAppCDOTDataMotionTestCase(test.TestCase): 

41 

42 def setUp(self): 

43 super(NetAppCDOTDataMotionTestCase, self).setUp() 

44 self.backend = 'backend1' 

45 self.force_rest_client = False 

46 self.mock_cmode_client = self.mock_object(client_cmode, 

47 "NetAppCmodeClient", 

48 mock.Mock()) 

49 self.config = configuration.Configuration(driver.share_opts, 

50 config_group=self.backend) 

51 self.config.append_config_values(na_opts.netapp_cluster_opts) 

52 self.config.append_config_values(na_opts.netapp_connection_opts) 

53 self.config.append_config_values(na_opts.netapp_basicauth_opts) 

54 self.config.append_config_values(na_opts.netapp_certificateauth_opts) 

55 self.config.append_config_values(na_opts.netapp_transport_opts) 

56 self.config.append_config_values(na_opts.netapp_support_opts) 

57 self.config.append_config_values(na_opts.netapp_provisioning_opts) 

58 self.config.append_config_values(na_opts.netapp_data_motion_opts) 

59 CONF.set_override("share_backend_name", self.backend, 

60 group=self.backend) 

61 CONF.set_override("netapp_transport_type", "https", 

62 group=self.backend) 

63 CONF.set_override("netapp_login", "fake_user", 

64 group=self.backend) 

65 CONF.set_override("netapp_password", "fake_password", 

66 group=self.backend) 

67 CONF.set_override("netapp_server_hostname", "fake.hostname", 

68 group=self.backend) 

69 CONF.set_override("netapp_server_port", 8866, 

70 group=self.backend) 

71 CONF.set_override("netapp_ssl_cert_path", "/etc/ssl/certs", 

72 group=self.backend) 

73 CONF.set_override("netapp_private_key_file", "/fake_private_key.pem", 

74 group=self.backend) 

75 CONF.set_override("netapp_certificate_file", "/fake_cert.pem", 

76 group=self.backend) 

77 CONF.set_override("netapp_ca_certificate_file", "/fake_ca_cert.crt", 

78 group=self.backend) 

79 CONF.set_override("netapp_certificate_host_validation", False, 

80 group=self.backend) 

81 

82 def test_get_client_for_backend(self): 

83 self.mock_object(data_motion, "get_backend_configuration", 

84 mock.Mock(return_value=self.config)) 

85 

86 data_motion.get_client_for_backend(self.backend, 

87 self.force_rest_client) 

88 

89 self.mock_cmode_client.assert_called_once_with( 

90 hostname='fake.hostname', password='fake_password', 

91 username='fake_user', transport_type='https', port=8866, 

92 ssl_cert_path='/etc/ssl/certs', trace=mock.ANY, vserver=None, 

93 private_key_file='/fake_private_key.pem', 

94 certificate_file='/fake_cert.pem', 

95 ca_certificate_file='/fake_ca_cert.crt', 

96 certificate_host_validation=False) 

97 

98 def test_get_client_for_backend_with_vserver(self): 

99 self.mock_object(data_motion, "get_backend_configuration", 

100 mock.Mock(return_value=self.config)) 

101 

102 CONF.set_override("netapp_vserver", 'fake_vserver', 

103 group=self.backend) 

104 

105 data_motion.get_client_for_backend(self.backend) 

106 

107 self.mock_cmode_client.assert_called_once_with( 

108 hostname='fake.hostname', password='fake_password', 

109 username='fake_user', transport_type='https', port=8866, 

110 ssl_cert_path='/etc/ssl/certs', trace=mock.ANY, 

111 vserver='fake_vserver', 

112 private_key_file='/fake_private_key.pem', 

113 certificate_file='/fake_cert.pem', 

114 ca_certificate_file='/fake_ca_cert.crt', 

115 certificate_host_validation=False) 

116 

117 def test_get_client_for_host(self): 

118 mock_extract_host = self.mock_object( 

119 share_utils, 'extract_host', 

120 mock.Mock(return_value=fake.BACKEND_NAME)) 

121 mock_get_client = self.mock_object( 

122 data_motion, 'get_client_for_backend', 

123 mock.Mock(return_value=self.mock_cmode_client)) 

124 

125 returned_client = data_motion.get_client_for_host( 

126 fake.HOST_NAME) 

127 

128 mock_extract_host.assert_called_once_with( 

129 fake.HOST_NAME, level='backend_name') 

130 mock_get_client.assert_called_once_with(fake.BACKEND_NAME) 

131 self.assertEqual(returned_client, self.mock_cmode_client) 

132 

133 def test_get_config_for_backend(self): 

134 self.mock_object(data_motion, "CONF") 

135 

136 CONF.set_override("netapp_vserver", 'fake_vserver', 

137 group=self.backend) 

138 

139 CONF.set_override("driver_handles_share_servers", False, 

140 group=self.backend) 

141 

142 config = data_motion.get_backend_configuration(self.backend) 

143 

144 self.assertEqual('fake_vserver', config.netapp_vserver) 

145 

146 def test_get_config_for_backend_different_backend_name(self): 

147 self.mock_object(data_motion, "CONF") 

148 CONF.set_override("netapp_vserver", 'fake_vserver', 

149 group=self.backend) 

150 CONF.set_override("share_backend_name", "fake_backend_name", 

151 group=self.backend) 

152 

153 CONF.set_override("driver_handles_share_servers", False, 

154 group=self.backend) 

155 

156 config = data_motion.get_backend_configuration(self.backend) 

157 

158 self.assertEqual('fake_vserver', config.netapp_vserver) 

159 self.assertEqual('fake_backend_name', config.share_backend_name) 

160 

161 @ddt.data([], ['fake_backend1', 'fake_backend2']) 

162 def test_get_config_for_backend_not_configured(self, conf_sections): 

163 self.mock_object(data_motion, "CONF") 

164 

165 self.assertRaises(exception.BadConfigurationException, 

166 data_motion.get_backend_configuration, 

167 self.backend) 

168 

169 

170@ddt.ddt 

171class NetAppCDOTDataMotionSessionTestCase(test.TestCase): 

172 

173 def setUp(self): 

174 super(NetAppCDOTDataMotionSessionTestCase, self).setUp() 

175 

176 self.sleep_patcher = mock.patch.object(time, 'sleep', lambda s: None) 

177 self.sleep_patcher.start() 

178 self.addCleanup(self.sleep_patcher.stop) 

179 

180 self.source_backend = 'backend1' 

181 self.dest_backend = 'backend2' 

182 

183 config = configuration.Configuration(driver.share_opts, 

184 config_group=self.source_backend) 

185 config.append_config_values(na_opts.netapp_cluster_opts) 

186 config.append_config_values(na_opts.netapp_connection_opts) 

187 config.append_config_values(na_opts.netapp_basicauth_opts) 

188 config.append_config_values(na_opts.netapp_certificateauth_opts) 

189 config.append_config_values(na_opts.netapp_transport_opts) 

190 config.append_config_values(na_opts.netapp_support_opts) 

191 config.append_config_values(na_opts.netapp_provisioning_opts) 

192 config.append_config_values(na_opts.netapp_data_motion_opts) 

193 

194 self.mock_object(data_motion, "get_backend_configuration", 

195 mock.Mock(return_value=config)) 

196 

197 self.mock_cmode_client = self.mock_object(client_cmode, 

198 "NetAppCmodeClient", 

199 mock.Mock()) 

200 self.dm_session = data_motion.DataMotionSession() 

201 self.fake_src_share = copy.deepcopy(fake.SHARE) 

202 self.fake_src_share_server = copy.deepcopy(fake.SHARE_SERVER) 

203 self.source_vserver = 'source_vserver' 

204 self.source_backend_name = ( 

205 self.fake_src_share_server['host'].split('@')[1]) 

206 self.fake_src_share_server['backend_details']['vserver_name'] = ( 

207 self.source_vserver 

208 ) 

209 self.fake_src_share['share_server'] = self.fake_src_share_server 

210 self.fake_src_share['id'] = 'c02d497a-236c-4852-812a-0d39373e312a' 

211 self.fake_src_vol_name = 'share_c02d497a_236c_4852_812a_0d39373e312a' 

212 self.fake_dest_share = copy.deepcopy(fake.SHARE) 

213 self.fake_dest_share_server = copy.deepcopy(fake.SHARE_SERVER_2) 

214 self.dest_vserver = 'dest_vserver' 

215 self.dest_backend_name = ( 

216 self.fake_dest_share_server['host'].split('@')[1]) 

217 self.fake_dest_share_server['backend_details']['vserver_name'] = ( 

218 self.dest_vserver 

219 ) 

220 self.fake_dest_share['share_server'] = self.fake_dest_share_server 

221 self.fake_dest_share['id'] = '34fbaf57-745d-460f-8270-3378c2945e30' 

222 self.fake_dest_vol_name = 'share_34fbaf57_745d_460f_8270_3378c2945e30' 

223 

224 self.mock_src_client = mock.Mock() 

225 self.mock_dest_client = mock.Mock() 

226 self.mock_object(data_motion, 'get_client_for_backend', 

227 mock.Mock(side_effect=[self.mock_dest_client, 

228 self.mock_src_client])) 

229 self.mock_object(self.dm_session, 'get_client_and_vserver_name', 

230 mock.Mock(side_effect=[ 

231 (self.mock_src_client, self.source_vserver), 

232 (self.mock_dest_client, self.dest_vserver)])) 

233 

234 def test_get_client_and_vserver_name(self): 

235 dm_session = data_motion.DataMotionSession() 

236 client = mock.Mock() 

237 self.mock_object(data_motion, 'get_client_for_backend', 

238 mock.Mock(return_value=client)) 

239 

240 result = dm_session.get_client_and_vserver_name(fake.SHARE_SERVER) 

241 expected = (client, 

242 fake.SHARE_SERVER['backend_details']['vserver_name']) 

243 

244 self.assertEqual(expected, result) 

245 data_motion.get_client_for_backend.assert_called_once_with( 

246 fake.BACKEND_NAME, vserver_name=fake.VSERVER1 

247 ) 

248 

249 @ddt.data(True, False) 

250 def test_create_snapmirror_mount(self, mount): 

251 mock_dest_client = mock.Mock() 

252 self.mock_object(data_motion, 'get_client_for_backend', 

253 mock.Mock(return_value=mock_dest_client)) 

254 self.mock_object(self.dm_session, 'wait_for_mount_replica') 

255 mock_backend_config = na_fakes.create_configuration() 

256 mock_backend_config.netapp_mount_replica_timeout = 30 

257 self.mock_object(data_motion, 'get_backend_configuration', 

258 mock.Mock(return_value=mock_backend_config)) 

259 

260 self.dm_session.create_snapmirror(self.fake_src_share, 

261 self.fake_dest_share, 

262 'data_protection', mount=mount) 

263 

264 mock_dest_client.create_snapmirror_vol.assert_called_once_with( 

265 mock.ANY, self.fake_src_vol_name, mock.ANY, 

266 self.fake_dest_vol_name, 'data_protection', schedule='hourly' 

267 ) 

268 mock_dest_client.initialize_snapmirror_vol.assert_called_once_with( 

269 mock.ANY, self.fake_src_vol_name, mock.ANY, 

270 self.fake_dest_vol_name 

271 ) 

272 if mount: 

273 self.dm_session.wait_for_mount_replica.assert_called_once_with( 

274 mock_dest_client, self.fake_dest_vol_name, timeout=30) 

275 else: 

276 self.dm_session.wait_for_mount_replica.assert_not_called() 

277 

278 def test_create_snapmirror_svm(self): 

279 mock_dest_client = mock.Mock() 

280 self.mock_object(self.dm_session, 'get_client_and_vserver_name', 

281 mock.Mock(return_value=(mock_dest_client, 

282 self.dest_vserver))) 

283 self.mock_object(self.dm_session, 'get_vserver_from_share_server', 

284 mock.Mock(return_value=self.source_vserver)) 

285 policy_name = 'policy_' + self.dest_vserver 

286 get_snapmirro_policy_name = self.mock_object( 

287 self.dm_session, '_get_backend_snapmirror_policy_name_svm', 

288 mock.Mock(return_value=policy_name)) 

289 

290 self.dm_session.create_snapmirror_svm(self.fake_src_share_server, 

291 self.fake_dest_share_server) 

292 

293 self.dm_session.get_client_and_vserver_name.assert_called_once_with( 

294 self.fake_dest_share_server 

295 ) 

296 self.dm_session.get_vserver_from_share_server.assert_called_once_with( 

297 self.fake_src_share_server 

298 ) 

299 get_snapmirro_policy_name.assert_called_once_with( 

300 self.fake_dest_share_server['id'], self.dest_backend_name 

301 ) 

302 mock_dest_client.create_snapmirror_policy.assert_called_once_with( 

303 policy_name 

304 ) 

305 mock_dest_client.create_snapmirror_svm.assert_called_once_with( 

306 self.source_vserver, self.dest_vserver, 

307 policy=policy_name, schedule='hourly' 

308 ) 

309 mock_dest_client.initialize_snapmirror_svm.assert_called_once_with( 

310 self.source_vserver, self.dest_vserver 

311 ) 

312 

313 def test_delete_snapmirror(self): 

314 mock_src_client = mock.Mock() 

315 mock_dest_client = mock.Mock() 

316 self.mock_object(data_motion, 'get_client_for_backend', 

317 mock.Mock(side_effect=[mock_dest_client, 

318 mock_src_client])) 

319 mock_backend_config = na_fakes.create_configuration() 

320 mock_backend_config.netapp_snapmirror_release_timeout = 30 

321 self.mock_object(data_motion, 'get_backend_configuration', 

322 mock.Mock(return_value=mock_backend_config)) 

323 mock_wait_for_snapmirror_release_vol = self.mock_object( 

324 self.dm_session, 'wait_for_snapmirror_release_vol') 

325 

326 self.dm_session.delete_snapmirror(self.fake_src_share, 

327 self.fake_dest_share) 

328 

329 mock_dest_client.abort_snapmirror_vol.assert_called_once_with( 

330 mock.ANY, self.fake_src_vol_name, mock.ANY, 

331 self.fake_dest_vol_name, clear_checkpoint=False 

332 ) 

333 mock_dest_client.delete_snapmirror_vol.assert_called_once_with( 

334 mock.ANY, self.fake_src_vol_name, mock.ANY, 

335 self.fake_dest_vol_name 

336 ) 

337 mock_wait_for_snapmirror_release_vol.assert_called_once_with( 

338 self.source_vserver, self.dest_vserver, self.fake_src_vol_name, 

339 self.fake_dest_vol_name, False, mock_src_client, 

340 timeout=30 

341 ) 

342 

343 @ddt.data(True, False) 

344 def test_delete_snapmirror_svm(self, call_release): 

345 self.mock_object(self.dm_session, 'wait_for_snapmirror_release_svm') 

346 mock_backend_config = na_fakes.create_configuration() 

347 mock_backend_config.netapp_snapmirror_release_timeout = 30 

348 self.mock_object(data_motion, 'get_backend_configuration', 

349 mock.Mock(return_value=mock_backend_config)) 

350 

351 self.dm_session.delete_snapmirror_svm(self.fake_src_share_server, 

352 self.fake_dest_share_server, 

353 release=call_release) 

354 

355 self.mock_dest_client.abort_snapmirror_svm.assert_called_once_with( 

356 self.source_vserver, self.dest_vserver 

357 ) 

358 self.mock_dest_client.delete_snapmirror_svm.assert_called_once_with( 

359 self.source_vserver, self.dest_vserver 

360 ) 

361 if call_release: 

362 release_mock = self.dm_session.wait_for_snapmirror_release_svm 

363 release_mock.assert_called_once_with( 

364 self.source_vserver, self.dest_vserver, self.mock_src_client, 

365 timeout=mock_backend_config.netapp_snapmirror_release_timeout 

366 ) 

367 

368 def test_delete_snapmirror_does_not_exist(self): 

369 """Ensure delete succeeds when the snapmirror does not exist.""" 

370 mock_src_client = mock.Mock() 

371 mock_dest_client = mock.Mock() 

372 mock_dest_client.abort_snapmirror_vol.side_effect = ( 

373 netapp_api.NaApiError(code=netapp_api.EAPIERROR)) 

374 self.mock_object(data_motion, 'get_client_for_backend', 

375 mock.Mock(side_effect=[mock_dest_client, 

376 mock_src_client])) 

377 mock_backend_config = na_fakes.create_configuration() 

378 mock_backend_config.netapp_snapmirror_release_timeout = 30 

379 self.mock_object(data_motion, 'get_backend_configuration', 

380 mock.Mock(return_value=mock_backend_config)) 

381 mock_wait_for_snapmirror_release_vol = self.mock_object( 

382 self.dm_session, 'wait_for_snapmirror_release_vol') 

383 

384 self.dm_session.delete_snapmirror(self.fake_src_share, 

385 self.fake_dest_share) 

386 

387 mock_dest_client.abort_snapmirror_vol.assert_called_once_with( 

388 mock.ANY, self.fake_src_vol_name, mock.ANY, 

389 self.fake_dest_vol_name, clear_checkpoint=False 

390 ) 

391 mock_dest_client.delete_snapmirror_vol.assert_called_once_with( 

392 mock.ANY, self.fake_src_vol_name, mock.ANY, 

393 self.fake_dest_vol_name 

394 ) 

395 mock_wait_for_snapmirror_release_vol.assert_called_once_with( 

396 self.source_vserver, self.dest_vserver, self.fake_src_vol_name, 

397 self.fake_dest_vol_name, False, mock_src_client, 

398 timeout=30 

399 ) 

400 

401 def test_delete_snapmirror_svm_does_not_exist(self): 

402 """Ensure delete succeeds when the snapmirror does not exist.""" 

403 self.mock_dest_client.abort_snapmirror_svm.side_effect = ( 

404 netapp_api.NaApiError(code=netapp_api.EAPIERROR)) 

405 self.mock_object(self.dm_session, 'wait_for_snapmirror_release_svm') 

406 mock_backend_config = na_fakes.create_configuration() 

407 mock_backend_config.netapp_snapmirror_release_timeout = 30 

408 self.mock_object(data_motion, 'get_backend_configuration', 

409 mock.Mock(return_value=mock_backend_config)) 

410 

411 self.dm_session.delete_snapmirror_svm(self.fake_src_share_server, 

412 self.fake_dest_share_server) 

413 

414 self.mock_dest_client.abort_snapmirror_svm.assert_called_once_with( 

415 self.source_vserver, self.dest_vserver 

416 ) 

417 self.mock_dest_client.delete_snapmirror_svm.assert_called_once_with( 

418 self.source_vserver, self.dest_vserver 

419 ) 

420 release_mock = self.dm_session.wait_for_snapmirror_release_svm 

421 release_mock.assert_called_once_with( 

422 self.source_vserver, self.dest_vserver, self.mock_src_client, 

423 timeout=mock_backend_config.netapp_snapmirror_release_timeout 

424 ) 

425 

426 def test_delete_snapmirror_error_deleting(self): 

427 """Ensure delete succeeds when the snapmirror does not exist.""" 

428 mock_src_client = mock.Mock() 

429 mock_dest_client = mock.Mock() 

430 mock_dest_client.delete_snapmirror_vol.side_effect = ( 

431 netapp_api.NaApiError(code=netapp_api.ESOURCE_IS_DIFFERENT)) 

432 self.mock_object(data_motion, 'get_client_for_backend', 

433 mock.Mock(side_effect=[mock_dest_client, 

434 mock_src_client])) 

435 mock_backend_config = na_fakes.create_configuration() 

436 mock_backend_config.netapp_snapmirror_release_timeout = 30 

437 self.mock_object(data_motion, 'get_backend_configuration', 

438 mock.Mock(return_value=mock_backend_config)) 

439 mock_wait_for_snapmirror_release_vol = self.mock_object( 

440 self.dm_session, 'wait_for_snapmirror_release_vol') 

441 

442 self.dm_session.delete_snapmirror(self.fake_src_share, 

443 self.fake_dest_share) 

444 

445 mock_dest_client.abort_snapmirror_vol.assert_called_once_with( 

446 mock.ANY, self.fake_src_vol_name, mock.ANY, 

447 self.fake_dest_vol_name, clear_checkpoint=False 

448 ) 

449 mock_dest_client.delete_snapmirror_vol.assert_called_once_with( 

450 mock.ANY, self.fake_src_vol_name, mock.ANY, 

451 self.fake_dest_vol_name 

452 ) 

453 mock_wait_for_snapmirror_release_vol.assert_called_once_with( 

454 self.source_vserver, self.dest_vserver, self.fake_src_vol_name, 

455 self.fake_dest_vol_name, False, mock_src_client, 

456 timeout=30 

457 ) 

458 

459 def test_delete_snapmirror_svm_error_deleting(self): 

460 """Ensure delete succeeds when the snapmirror does not exist.""" 

461 self.mock_dest_client.delete_snapmirror_svm.side_effect = ( 

462 netapp_api.NaApiError(code=netapp_api.ESOURCE_IS_DIFFERENT)) 

463 self.mock_object(self.dm_session, 'wait_for_snapmirror_release_svm') 

464 mock_backend_config = na_fakes.create_configuration() 

465 mock_backend_config.netapp_snapmirror_release_timeout = 30 

466 self.mock_object(data_motion, 'get_backend_configuration', 

467 mock.Mock(return_value=mock_backend_config)) 

468 

469 self.dm_session.delete_snapmirror_svm(self.fake_src_share_server, 

470 self.fake_dest_share_server) 

471 

472 self.mock_dest_client.abort_snapmirror_svm.assert_called_once_with( 

473 self.source_vserver, self.dest_vserver 

474 ) 

475 self.mock_dest_client.delete_snapmirror_svm.assert_called_once_with( 

476 self.source_vserver, self.dest_vserver 

477 ) 

478 release_mock = self.dm_session.wait_for_snapmirror_release_svm 

479 release_mock.assert_called_once_with( 

480 self.source_vserver, self.dest_vserver, self.mock_src_client, 

481 timeout=mock_backend_config.netapp_snapmirror_release_timeout 

482 ) 

483 

484 def test_delete_snapmirror_without_release(self): 

485 mock_src_client = mock.Mock() 

486 mock_dest_client = mock.Mock() 

487 self.mock_object(data_motion, 'get_client_for_backend', 

488 mock.Mock(side_effect=[mock_dest_client, 

489 mock_src_client])) 

490 mock_wait_for_snapmirror_release_vol = self.mock_object( 

491 self.dm_session, 'wait_for_snapmirror_release_vol') 

492 

493 self.dm_session.delete_snapmirror(self.fake_src_share, 

494 self.fake_dest_share, 

495 release=False) 

496 

497 mock_dest_client.abort_snapmirror_vol.assert_called_once_with( 

498 mock.ANY, self.fake_src_vol_name, mock.ANY, 

499 self.fake_dest_vol_name, clear_checkpoint=False 

500 ) 

501 mock_dest_client.delete_snapmirror_vol.assert_called_once_with( 

502 mock.ANY, self.fake_src_vol_name, mock.ANY, 

503 self.fake_dest_vol_name 

504 ) 

505 self.assertFalse(mock_wait_for_snapmirror_release_vol.called) 

506 

507 def test_delete_snapmirror_source_unreachable(self): 

508 mock_dest_client = mock.Mock() 

509 self.mock_object(data_motion, 'get_client_for_backend', 

510 mock.Mock(side_effect=[mock_dest_client, 

511 Exception])) 

512 mock_wait_for_snapmirror_release_vol = self.mock_object( 

513 self.dm_session, 'wait_for_snapmirror_release_vol') 

514 

515 self.dm_session.delete_snapmirror(self.fake_src_share, 

516 self.fake_dest_share) 

517 

518 mock_dest_client.abort_snapmirror_vol.assert_called_once_with( 

519 mock.ANY, self.fake_src_vol_name, mock.ANY, 

520 self.fake_dest_vol_name, clear_checkpoint=False 

521 ) 

522 mock_dest_client.delete_snapmirror_vol.assert_called_once_with( 

523 mock.ANY, self.fake_src_vol_name, mock.ANY, 

524 self.fake_dest_vol_name 

525 ) 

526 self.assertFalse(mock_wait_for_snapmirror_release_vol.called) 

527 

528 def test_break_snapmirror(self): 

529 self.mock_object(self.dm_session, 'quiesce_then_abort') 

530 

531 self.dm_session.break_snapmirror(self.fake_src_share, 

532 self.fake_dest_share) 

533 

534 self.mock_dest_client.break_snapmirror_vol.assert_called_once_with( 

535 self.source_vserver, self.fake_src_vol_name, 

536 self.dest_vserver, self.fake_dest_vol_name) 

537 

538 self.dm_session.quiesce_then_abort.assert_called_once_with( 

539 self.fake_src_share, self.fake_dest_share, 

540 quiesce_wait_time=None) 

541 

542 self.mock_dest_client.mount_volume.assert_called_once_with( 

543 self.fake_dest_vol_name) 

544 

545 def test_break_snapmirror_no_mount(self): 

546 self.mock_object(self.dm_session, 'quiesce_then_abort') 

547 

548 self.dm_session.break_snapmirror(self.fake_src_share, 

549 self.fake_dest_share, 

550 mount=False) 

551 

552 self.mock_dest_client.break_snapmirror_vol.assert_called_once_with( 

553 self.source_vserver, self.fake_src_vol_name, 

554 self.dest_vserver, self.fake_dest_vol_name) 

555 

556 self.dm_session.quiesce_then_abort.assert_called_once_with( 

557 self.fake_src_share, self.fake_dest_share, 

558 quiesce_wait_time=None) 

559 

560 self.assertFalse(self.mock_dest_client.mount_volume.called) 

561 

562 def test_break_snapmirror_wait_for_quiesced(self): 

563 self.mock_object(self.dm_session, 'quiesce_then_abort') 

564 

565 self.dm_session.break_snapmirror(self.fake_src_share, 

566 self.fake_dest_share) 

567 

568 self.dm_session.quiesce_then_abort.assert_called_once_with( 

569 self.fake_src_share, self.fake_dest_share, 

570 quiesce_wait_time=None) 

571 

572 self.mock_dest_client.break_snapmirror_vol.assert_called_once_with( 

573 self.source_vserver, self.fake_src_vol_name, 

574 self.dest_vserver, self.fake_dest_vol_name) 

575 

576 self.mock_dest_client.mount_volume.assert_called_once_with( 

577 self.fake_dest_vol_name) 

578 

579 @ddt.data(None, 2, 30) 

580 def test_quiesce_then_abort_wait_time(self, wait_time): 

581 self.mock_object(time, 'sleep') 

582 mock_get_snapmirrors = mock.Mock( 

583 return_value=[{'relationship-status': "transferring"}]) 

584 self.mock_object(self.mock_dest_client, 'get_snapmirrors', 

585 mock_get_snapmirrors) 

586 mock_backend_config = na_fakes.create_configuration() 

587 mock_backend_config.netapp_snapmirror_quiesce_timeout = 10 

588 self.mock_object(data_motion, 'get_backend_configuration', 

589 mock.Mock(return_value=mock_backend_config)) 

590 

591 self.dm_session.quiesce_then_abort(self.fake_src_share, 

592 self.fake_dest_share, 

593 quiesce_wait_time=wait_time) 

594 

595 self.mock_dest_client.get_snapmirrors.assert_called_with( 

596 source_vserver=self.source_vserver, 

597 dest_vserver=self.dest_vserver, 

598 source_volume=self.fake_src_vol_name, 

599 dest_volume=self.fake_dest_vol_name, 

600 desired_attributes=['relationship-status', 'mirror-state'] 

601 ) 

602 

603 call_count = self.mock_dest_client.get_snapmirrors.call_count 

604 if wait_time: 

605 if wait_time > 5: 

606 self.assertEqual(wait_time / 5, call_count) 

607 else: 

608 self.assertEqual(1, call_count) 

609 else: 

610 self.assertEqual(2, call_count) 

611 

612 def test_quiesce_then_abort_timeout(self): 

613 self.mock_object(time, 'sleep') 

614 mock_get_snapmirrors = mock.Mock( 

615 return_value=[{'relationship-status': "transferring"}]) 

616 self.mock_object(self.mock_dest_client, 'get_snapmirrors', 

617 mock_get_snapmirrors) 

618 mock_backend_config = na_fakes.create_configuration() 

619 mock_backend_config.netapp_snapmirror_quiesce_timeout = 10 

620 self.mock_object(data_motion, 'get_backend_configuration', 

621 mock.Mock(return_value=mock_backend_config)) 

622 

623 self.dm_session.quiesce_then_abort(self.fake_src_share, 

624 self.fake_dest_share) 

625 

626 self.mock_dest_client.get_snapmirrors.assert_called_with( 

627 source_vserver=self.source_vserver, 

628 dest_vserver=self.dest_vserver, 

629 source_volume=self.fake_src_vol_name, 

630 dest_volume=self.fake_dest_vol_name, 

631 desired_attributes=['relationship-status', 'mirror-state'] 

632 ) 

633 self.assertEqual(2, self.mock_dest_client.get_snapmirrors.call_count) 

634 

635 self.mock_dest_client.quiesce_snapmirror_vol.assert_called_with( 

636 self.source_vserver, self.fake_src_vol_name, 

637 self.dest_vserver, self.fake_dest_vol_name) 

638 

639 self.mock_dest_client.abort_snapmirror_vol.assert_called_once_with( 

640 self.source_vserver, self.fake_src_vol_name, 

641 self.dest_vserver, self.fake_dest_vol_name, 

642 clear_checkpoint=False 

643 ) 

644 

645 def test_quiesce_then_abort_svm_timeout(self): 

646 self.mock_object(time, 'sleep') 

647 mock_get_snapmirrors = mock.Mock( 

648 return_value=[{'relationship-status': "transferring"}]) 

649 self.mock_object(self.mock_dest_client, 'get_snapmirrors_svm', 

650 mock_get_snapmirrors) 

651 mock_backend_config = na_fakes.create_configuration() 

652 mock_backend_config.netapp_snapmirror_quiesce_timeout = 10 

653 self.mock_object(data_motion, 'get_backend_configuration', 

654 mock.Mock(return_value=mock_backend_config)) 

655 

656 self.dm_session.quiesce_then_abort_svm(self.fake_src_share_server, 

657 self.fake_dest_share_server) 

658 

659 self.mock_dest_client.get_snapmirrors_svm.assert_called_with( 

660 source_vserver=self.source_vserver, 

661 dest_vserver=self.dest_vserver, 

662 desired_attributes=['relationship-status', 'mirror-state'] 

663 ) 

664 self.assertEqual(2, 

665 self.mock_dest_client.get_snapmirrors_svm.call_count) 

666 

667 self.mock_dest_client.quiesce_snapmirror_svm.assert_called_with( 

668 self.source_vserver, self.dest_vserver) 

669 

670 self.mock_dest_client.abort_snapmirror_svm.assert_called_once_with( 

671 self.source_vserver, self.dest_vserver, 

672 clear_checkpoint=False 

673 ) 

674 

675 def test_quiesce_then_abort_wait_for_quiesced(self): 

676 self.mock_object(time, 'sleep') 

677 self.mock_object(self.mock_dest_client, 'get_snapmirrors', 

678 mock.Mock(side_effect=[ 

679 [{'relationship-status': "transferring"}], 

680 [{'relationship-status': "quiesced"}]])) 

681 

682 self.dm_session.quiesce_then_abort(self.fake_src_share, 

683 self.fake_dest_share) 

684 

685 self.mock_dest_client.get_snapmirrors.assert_called_with( 

686 source_vserver=self.source_vserver, 

687 dest_vserver=self.dest_vserver, 

688 source_volume=self.fake_src_vol_name, 

689 dest_volume=self.fake_dest_vol_name, 

690 desired_attributes=['relationship-status', 'mirror-state'] 

691 ) 

692 self.assertEqual(2, self.mock_dest_client.get_snapmirrors.call_count) 

693 

694 self.mock_dest_client.quiesce_snapmirror_vol.assert_called_once_with( 

695 self.source_vserver, self.fake_src_vol_name, 

696 self.dest_vserver, self.fake_dest_vol_name) 

697 

698 def test_quiesce_then_abort_svm_wait_for_quiesced(self): 

699 self.mock_object(time, 'sleep') 

700 self.mock_object(self.mock_dest_client, 'get_snapmirrors_svm', 

701 mock.Mock(side_effect=[ 

702 [{'relationship-status': "transferring"}], 

703 [{'relationship-status': "quiesced"}]])) 

704 

705 self.dm_session.quiesce_then_abort_svm(self.fake_src_share_server, 

706 self.fake_dest_share_server) 

707 

708 self.mock_dest_client.get_snapmirrors_svm.assert_called_with( 

709 source_vserver=self.source_vserver, 

710 dest_vserver=self.dest_vserver, 

711 desired_attributes=['relationship-status', 'mirror-state'] 

712 ) 

713 self.assertEqual(2, 

714 self.mock_dest_client.get_snapmirrors_svm.call_count) 

715 

716 self.mock_dest_client.quiesce_snapmirror_svm.assert_called_once_with( 

717 self.source_vserver, self.dest_vserver) 

718 

719 def test_resync_snapmirror(self): 

720 self.dm_session.resync_snapmirror(self.fake_src_share, 

721 self.fake_dest_share) 

722 

723 self.mock_dest_client.resync_snapmirror_vol.assert_called_once_with( 

724 self.source_vserver, self.fake_src_vol_name, 

725 self.dest_vserver, self.fake_dest_vol_name) 

726 

727 def test_change_snapmirror_source(self): 

728 fake_new_src_share = copy.deepcopy(fake.SHARE) 

729 fake_new_src_share['id'] = 'd02d497a-236c-4852-812a-0d39373e312a' 

730 fake_new_src_share_name = 'share_d02d497a_236c_4852_812a_0d39373e312a' 

731 mock_new_src_client = mock.Mock() 

732 self.mock_object(self.dm_session, 'delete_snapmirror') 

733 self.mock_object(data_motion, 'get_client_for_backend', 

734 mock.Mock(side_effect=[self.mock_dest_client, 

735 self.mock_src_client, 

736 self.mock_dest_client, 

737 mock_new_src_client])) 

738 self.mock_object(na_utils, 'get_relationship_type', 

739 mock.Mock(return_value=na_utils.DATA_PROTECTION_TYPE)) 

740 

741 self.dm_session.change_snapmirror_source( 

742 self.fake_dest_share, self.fake_src_share, fake_new_src_share, 

743 [self.fake_dest_share, self.fake_src_share, fake_new_src_share]) 

744 

745 self.assertFalse(self.mock_src_client.release_snapmirror_vol.called) 

746 

747 self.assertEqual(4, self.dm_session.delete_snapmirror.call_count) 

748 self.dm_session.delete_snapmirror.assert_called_with( 

749 mock.ANY, mock.ANY, release=False, relationship_info_only=False 

750 ) 

751 

752 na_utils.get_relationship_type.assert_called_once_with(False) 

753 self.mock_dest_client.create_snapmirror_vol.assert_called_once_with( 

754 mock.ANY, fake_new_src_share_name, mock.ANY, 

755 self.fake_dest_vol_name, na_utils.DATA_PROTECTION_TYPE, 

756 schedule='hourly' 

757 ) 

758 

759 self.mock_dest_client.resync_snapmirror_vol.assert_called_once_with( 

760 mock.ANY, fake_new_src_share_name, mock.ANY, 

761 self.fake_dest_vol_name 

762 ) 

763 

764 def test_change_snapmirror_source_dhss_true(self): 

765 fake_new_src_share = copy.deepcopy(self.fake_src_share) 

766 fake_new_src_share['id'] = 'd02d497a-236c-4852-812a-0d39373e312a' 

767 fake_new_src_share_name = 'share_d02d497a_236c_4852_812a_0d39373e312a' 

768 fake_new_src_share_server = fake_new_src_share['share_server'] 

769 fake_new_src_ss_name = ( 

770 fake_new_src_share_server['backend_details']['vserver_name']) 

771 self.mock_object(self.dm_session, 'delete_snapmirror') 

772 self.mock_object(data_motion, 'get_client_for_backend', 

773 mock.Mock(side_effect=[self.mock_dest_client, 

774 self.mock_src_client])) 

775 mock_backend_config = na_fakes.create_configuration() 

776 mock_backend_config.driver_handles_share_servers = True 

777 self.mock_object(data_motion, 'get_backend_configuration', 

778 mock.Mock(return_value=mock_backend_config)) 

779 self.mock_object(self.mock_dest_client, 'get_vserver_peers', 

780 mock.Mock(return_value=[])) 

781 peer_cluster_name = 'new_src_cluster_name' 

782 self.mock_object(self.mock_src_client, 'get_cluster_name', 

783 mock.Mock(return_value=peer_cluster_name)) 

784 self.mock_object(na_utils, 'get_relationship_type', 

785 mock.Mock(return_value=na_utils.DATA_PROTECTION_TYPE)) 

786 

787 self.dm_session.change_snapmirror_source( 

788 self.fake_dest_share, self.fake_src_share, fake_new_src_share, 

789 [self.fake_dest_share, self.fake_src_share, fake_new_src_share]) 

790 

791 self.assertEqual(4, self.dm_session.delete_snapmirror.call_count) 

792 

793 self.mock_dest_client.get_vserver_peers.assert_called_once_with( 

794 self.dest_vserver, fake_new_src_ss_name 

795 ) 

796 self.assertTrue(self.mock_src_client.get_cluster_name.called) 

797 self.mock_dest_client.create_vserver_peer.assert_called_once_with( 

798 self.dest_vserver, fake_new_src_ss_name, 

799 peer_cluster_name=peer_cluster_name 

800 ) 

801 self.mock_src_client.accept_vserver_peer.assert_called_once_with( 

802 fake_new_src_ss_name, self.dest_vserver 

803 ) 

804 na_utils.get_relationship_type.assert_called_once_with(False) 

805 self.dm_session.delete_snapmirror.assert_called_with( 

806 mock.ANY, mock.ANY, release=False, relationship_info_only=False 

807 ) 

808 self.mock_dest_client.create_snapmirror_vol.assert_called_once_with( 

809 mock.ANY, fake_new_src_share_name, mock.ANY, 

810 self.fake_dest_vol_name, na_utils.DATA_PROTECTION_TYPE, 

811 schedule='hourly' 

812 ) 

813 self.mock_dest_client.resync_snapmirror_vol.assert_called_once_with( 

814 mock.ANY, fake_new_src_share_name, mock.ANY, 

815 self.fake_dest_vol_name 

816 ) 

817 

818 def test_get_snapmirrors(self): 

819 self.mock_object(self.mock_dest_client, 'get_snapmirrors') 

820 

821 self.dm_session.get_snapmirrors(self.fake_src_share, 

822 self.fake_dest_share) 

823 

824 self.mock_dest_client.get_snapmirrors.assert_called_with( 

825 source_vserver=self.source_vserver, 

826 dest_vserver=self.dest_vserver, 

827 source_volume=self.fake_src_vol_name, 

828 dest_volume=self.fake_dest_vol_name, 

829 desired_attributes=['relationship-status', 

830 'mirror-state', 

831 'schedule', 

832 'source-vserver', 

833 'source-volume', 

834 'last-transfer-end-timestamp', 

835 'last-transfer-size', 

836 'last-transfer-error'] 

837 ) 

838 self.assertEqual(1, self.mock_dest_client.get_snapmirrors.call_count) 

839 

840 def test_get_snapmirrors_svm(self): 

841 mock_dest_client = mock.Mock() 

842 self.mock_object(self.dm_session, 'get_client_and_vserver_name', 

843 mock.Mock(return_value=(mock_dest_client, 

844 self.dest_vserver))) 

845 self.mock_object(mock_dest_client, 'get_snapmirrors_svm') 

846 

847 self.dm_session.get_snapmirrors_svm(self.fake_src_share_server, 

848 self.fake_dest_share_server) 

849 

850 mock_dest_client.get_snapmirrors_svm.assert_called_with( 

851 source_vserver=self.source_vserver, 

852 dest_vserver=self.dest_vserver, 

853 desired_attributes=['relationship-status', 

854 'mirror-state', 

855 'last-transfer-end-timestamp'] 

856 ) 

857 self.assertEqual(1, mock_dest_client.get_snapmirrors_svm.call_count) 

858 

859 def test_get_snapmirror_destinations_svm(self): 

860 mock_dest_client = mock.Mock() 

861 self.mock_object(self.dm_session, 'get_client_and_vserver_name', 

862 mock.Mock(return_value=(mock_dest_client, 

863 self.dest_vserver))) 

864 self.mock_object(mock_dest_client, 'get_snapmirror_destinations_svm') 

865 

866 self.dm_session.get_snapmirror_destinations_svm( 

867 self.fake_src_share_server, self.fake_dest_share_server) 

868 

869 mock_dest_client.get_snapmirror_destinations_svm.assert_called_with( 

870 source_vserver=self.source_vserver, 

871 dest_vserver=self.dest_vserver, 

872 ) 

873 self.assertEqual(1, mock_dest_client.get_snapmirror_destinations_svm 

874 .call_count) 

875 

876 def test_update_snapmirror(self): 

877 self.mock_object(self.mock_dest_client, 'get_snapmirrors') 

878 

879 self.dm_session.update_snapmirror(self.fake_src_share, 

880 self.fake_dest_share) 

881 

882 self.mock_dest_client.update_snapmirror_vol.assert_called_once_with( 

883 self.source_vserver, self.fake_src_vol_name, 

884 self.dest_vserver, self.fake_dest_vol_name) 

885 

886 def test_update_snapmirror_svm(self): 

887 mock_dest_client = mock.Mock() 

888 self.mock_object(self.dm_session, 'get_client_and_vserver_name', 

889 mock.Mock(return_value=(mock_dest_client, 

890 self.dest_vserver))) 

891 

892 self.dm_session.update_snapmirror_svm(self.fake_src_share_server, 

893 self.fake_dest_share_server) 

894 

895 mock_dest_client.update_snapmirror_svm.assert_called_once_with( 

896 self.source_vserver, self.dest_vserver) 

897 

898 def test_abort_and_break_snapmirror_svm(self): 

899 mock_dest_client = mock.Mock() 

900 self.mock_object(self.dm_session, 'get_client_and_vserver_name', 

901 mock.Mock(return_value=(mock_dest_client, 

902 self.dest_vserver))) 

903 self.mock_object(self.dm_session, 'quiesce_then_abort_svm') 

904 

905 self.dm_session.quiesce_and_break_snapmirror_svm( 

906 self.fake_src_share_server, self.fake_dest_share_server 

907 ) 

908 

909 self.dm_session.get_client_and_vserver_name.assert_called_once_with( 

910 self.fake_dest_share_server 

911 ) 

912 self.dm_session.quiesce_then_abort_svm.assert_called_once_with( 

913 self.fake_src_share_server, self.fake_dest_share_server 

914 ) 

915 mock_dest_client.break_snapmirror_svm(self.source_vserver, 

916 self.dest_vserver) 

917 

918 @ddt.data({'snapmirrors': ['fake_snapmirror'], 

919 'vserver_subtype': 'default'}, 

920 {'snapmirrors': [], 

921 'vserver_subtype': 'default'}, 

922 {'snapmirrors': [], 

923 'vserver_subtype': 'dp_destination'}) 

924 @ddt.unpack 

925 def test_cancel_snapmirror_svm(self, snapmirrors, vserver_subtype): 

926 mock_dest_client = mock.Mock() 

927 self.mock_object(self.dm_session, 'get_client_and_vserver_name', 

928 mock.Mock(return_value=(mock_dest_client, 

929 self.dest_vserver))) 

930 mock_backend_config = na_fakes.create_configuration() 

931 mock_backend_config.netapp_server_migration_state_change_timeout = 30 

932 self.mock_object(data_motion, 'get_backend_configuration', 

933 mock.Mock(return_value=mock_backend_config)) 

934 self.mock_object(self.dm_session, 'get_snapmirrors_svm', 

935 mock.Mock(return_value=snapmirrors)) 

936 self.mock_object(self.dm_session, 'quiesce_and_break_snapmirror_svm') 

937 self.mock_object(self.dm_session, 'wait_for_vserver_state') 

938 self.mock_object(self.dm_session, 'delete_snapmirror_svm') 

939 vserver_info = copy.deepcopy(fake.VSERVER_INFO) 

940 vserver_info['subtype'] = vserver_subtype 

941 self.mock_object(mock_dest_client, 'get_vserver_info', 

942 mock.Mock(return_value=vserver_info)) 

943 self.mock_object(self.dm_session, 'convert_svm_to_default_subtype') 

944 

945 self.dm_session.cancel_snapmirror_svm(self.fake_src_share_server, 

946 self.fake_dest_share_server) 

947 

948 data_motion.get_backend_configuration.assert_called_once_with( 

949 self.dest_backend_name 

950 ) 

951 self.dm_session.get_client_and_vserver_name.assert_called_once_with( 

952 self.fake_dest_share_server 

953 ) 

954 self.dm_session.get_snapmirrors_svm.assert_called_once_with( 

955 self.fake_src_share_server, self.fake_dest_share_server 

956 ) 

957 if snapmirrors: 

958 quiesce_mock = self.dm_session.quiesce_and_break_snapmirror_svm 

959 quiesce_mock.assert_called_once_with( 

960 self.fake_src_share_server, self.fake_dest_share_server 

961 ) 

962 self.dm_session.wait_for_vserver_state.assert_called_once_with( 

963 self.dest_vserver, mock_dest_client, subtype='default', 

964 state='running', operational_state='stopped', 

965 timeout=(mock_backend_config 

966 .netapp_server_migration_state_change_timeout) 

967 ) 

968 self.dm_session.delete_snapmirror_svm.assert_called_once_with( 

969 self.fake_src_share_server, self.fake_dest_share_server 

970 ) 

971 else: 

972 mock_dest_client.get_vserver_info.assert_called_once_with( 

973 self.dest_vserver 

974 ) 

975 convert_svm = self.dm_session.convert_svm_to_default_subtype 

976 if vserver_subtype == 'dp_destination': 

977 convert_svm.assert_called_once_with( 

978 self.dest_vserver, mock_dest_client, 

979 timeout=(mock_backend_config 

980 .netapp_server_migration_state_change_timeout) 

981 ) 

982 else: 

983 self.assertFalse(convert_svm.called) 

984 

985 def test_resume_snapmirror(self): 

986 self.mock_object(self.mock_dest_client, 'get_snapmirrors') 

987 

988 self.dm_session.resume_snapmirror(self.fake_src_share, 

989 self.fake_dest_share) 

990 

991 self.mock_dest_client.resume_snapmirror_vol.assert_called_once_with( 

992 self.source_vserver, self.fake_src_vol_name, 

993 self.dest_vserver, self.fake_dest_vol_name) 

994 

995 @ddt.data((None, exception.StorageCommunicationException), 

996 (exception.StorageCommunicationException, None)) 

997 @ddt.unpack 

998 def test_remove_qos_on_old_active_replica_unreachable_backend(self, 

999 side_eff_1, 

1000 side_eff_2): 

1001 mock_source_client = mock.Mock() 

1002 self.mock_object(data_motion, 'get_client_for_backend', 

1003 mock.Mock(return_value=mock_source_client)) 

1004 self.mock_object( 

1005 mock_source_client, 'set_qos_policy_group_for_volume', 

1006 mock.Mock(side_effect=side_eff_1)) 

1007 self.mock_object( 

1008 mock_source_client, 'mark_qos_policy_group_for_deletion', 

1009 mock.Mock(side_effect=side_eff_2)) 

1010 self.mock_object(data_motion.LOG, 'exception') 

1011 

1012 retval = self.dm_session.remove_qos_on_old_active_replica( 

1013 self.fake_src_share) 

1014 

1015 self.assertIsNone(retval) 

1016 (mock_source_client.set_qos_policy_group_for_volume 

1017 .assert_called_once_with(self.fake_src_vol_name, 'none')) 

1018 data_motion.LOG.exception.assert_called_once() 

1019 

1020 def test_remove_qos_on_old_active_replica(self): 

1021 mock_source_client = mock.Mock() 

1022 self.mock_object(data_motion, 'get_client_for_backend', 

1023 mock.Mock(return_value=mock_source_client)) 

1024 self.mock_object(data_motion.LOG, 'exception') 

1025 

1026 retval = self.dm_session.remove_qos_on_old_active_replica( 

1027 self.fake_src_share) 

1028 

1029 self.assertIsNone(retval) 

1030 (mock_source_client.set_qos_policy_group_for_volume 

1031 .assert_called_once_with(self.fake_src_vol_name, 'none')) 

1032 data_motion.LOG.exception.assert_not_called() 

1033 

1034 @ddt.data(True, False) 

1035 def test_convert_svm_to_default_subtype(self, is_dest): 

1036 mock_client = mock.Mock() 

1037 vserver_info_default = copy.deepcopy(fake.VSERVER_INFO) 

1038 vserver_info_default['subtype'] = 'default' 

1039 vserver_info_dp = copy.deepcopy(fake.VSERVER_INFO) 

1040 vserver_info_dp['subtype'] = 'dp_destination' 

1041 self.mock_object(mock_client, 'get_vserver_info', 

1042 mock.Mock(side_effect=[vserver_info_dp, 

1043 vserver_info_default])) 

1044 self.mock_object(mock_client, 'break_snapmirror_svm') 

1045 

1046 self.dm_session.convert_svm_to_default_subtype(fake.VSERVER1, 

1047 mock_client, 

1048 is_dest_path=is_dest, 

1049 timeout=20) 

1050 

1051 mock_client.get_vserver_info.assert_has_calls([ 

1052 mock.call(fake.VSERVER1), mock.call(fake.VSERVER1)]) 

1053 if is_dest: 

1054 mock_client.break_snapmirror_svm.assert_called_once_with( 

1055 dest_vserver=fake.VSERVER1 

1056 ) 

1057 else: 

1058 mock_client.break_snapmirror_svm.assert_called_once_with( 

1059 source_vserver=fake.VSERVER1 

1060 ) 

1061 

1062 def test_convert_svm_to_default_subtype_timeout(self): 

1063 mock_client = mock.Mock() 

1064 vserver_info_dp = copy.deepcopy(fake.VSERVER_INFO) 

1065 vserver_info_dp['subtype'] = 'dp_destination' 

1066 self.mock_object(mock_client, 'get_vserver_info', 

1067 mock.Mock(side_effect=[vserver_info_dp])) 

1068 self.mock_object(mock_client, 'break_snapmirror_svm') 

1069 

1070 self.assertRaises( 

1071 exception.NetAppException, 

1072 self.dm_session.convert_svm_to_default_subtype, 

1073 fake.VSERVER1, mock_client, is_dest_path=True, timeout=10) 

1074 

1075 mock_client.get_vserver_info.assert_called_once_with(fake.VSERVER1) 

1076 mock_client.break_snapmirror_svm.assert_called_once_with( 

1077 dest_vserver=fake.VSERVER1) 

1078 

1079 def test_wait_for_vserver_state(self,): 

1080 mock_client = mock.Mock() 

1081 vserver_info_default = copy.deepcopy(fake.VSERVER_INFO) 

1082 vserver_info_default['subtype'] = 'default' 

1083 vserver_info_dp = copy.deepcopy(fake.VSERVER_INFO) 

1084 vserver_info_dp['subtype'] = 'dp_destination' 

1085 self.mock_object(mock_client, 'get_vserver_info', 

1086 mock.Mock(side_effect=[vserver_info_dp, 

1087 vserver_info_default])) 

1088 

1089 self.dm_session.wait_for_vserver_state(fake.VSERVER1, mock_client, 

1090 state='running', 

1091 operational_state='running', 

1092 subtype='default', timeout=20) 

1093 

1094 mock_client.get_vserver_info.assert_has_calls([ 

1095 mock.call(fake.VSERVER1), mock.call(fake.VSERVER1)]) 

1096 

1097 def test_wait_for_vserver_state_timeout(self): 

1098 mock_client = mock.Mock() 

1099 vserver_info_dp = copy.deepcopy(fake.VSERVER_INFO) 

1100 vserver_info_dp['subtype'] = 'dp_destination' 

1101 self.mock_object(mock_client, 'get_vserver_info', 

1102 mock.Mock(side_effect=[vserver_info_dp])) 

1103 

1104 self.assertRaises( 

1105 exception.NetAppException, 

1106 self.dm_session.wait_for_vserver_state, 

1107 fake.VSERVER1, mock_client, state='running', 

1108 operational_state='running', subtype='default', timeout=10) 

1109 

1110 mock_client.get_vserver_info.assert_called_once_with(fake.VSERVER1) 

1111 

1112 @ddt.data(mock.Mock(), 

1113 mock.Mock(side_effect=netapp_api.NaApiError( 

1114 code=netapp_api.EOBJECTNOTFOUND))) 

1115 def test_wait_for_snapmirror_release_svm(self, release_snapmirror_ret): 

1116 src_mock_client = mock.Mock() 

1117 get_snapmirrors_mock = self.mock_object( 

1118 src_mock_client, 'get_snapmirror_destinations_svm', 

1119 mock.Mock(side_effect=[['fake_snapmirror'], []])) 

1120 self.mock_object(src_mock_client, 'release_snapmirror_svm', 

1121 release_snapmirror_ret) 

1122 

1123 self.dm_session.wait_for_snapmirror_release_svm(fake.VSERVER1, 

1124 fake.VSERVER2, 

1125 src_mock_client, 

1126 timeout=20) 

1127 get_snapmirrors_mock.assert_has_calls([ 

1128 mock.call(source_vserver=fake.VSERVER1, 

1129 dest_vserver=fake.VSERVER2), 

1130 mock.call(source_vserver=fake.VSERVER1, 

1131 dest_vserver=fake.VSERVER2)]) 

1132 src_mock_client.release_snapmirror_svm.assert_called_once_with( 

1133 fake.VSERVER1, fake.VSERVER2) 

1134 

1135 def test_wait_for_snapmirror_release_svm_timeout(self): 

1136 src_mock_client = mock.Mock() 

1137 get_snapmirrors_mock = self.mock_object( 

1138 src_mock_client, 'get_snapmirror_destinations_svm', 

1139 mock.Mock(side_effect=[['fake_snapmirror']])) 

1140 self.mock_object(src_mock_client, 'release_snapmirror_svm') 

1141 

1142 self.assertRaises(exception.NetAppException, 

1143 self.dm_session.wait_for_snapmirror_release_svm, 

1144 fake.VSERVER1, fake.VSERVER2, 

1145 src_mock_client, timeout=10) 

1146 

1147 get_snapmirrors_mock.assert_called_once_with( 

1148 source_vserver=fake.VSERVER1, dest_vserver=fake.VSERVER2) 

1149 src_mock_client.release_snapmirror_svm.assert_called_once_with( 

1150 fake.VSERVER1, fake.VSERVER2 

1151 ) 

1152 

1153 def test_wait_for_mount_replica(self): 

1154 

1155 mock_client = mock.Mock() 

1156 self.mock_object(time, 'sleep') 

1157 mock_warning_log = self.mock_object(data_motion.LOG, 'warning') 

1158 

1159 self.dm_session.wait_for_mount_replica( 

1160 mock_client, fake.SHARE_NAME) 

1161 

1162 mock_client.mount_volume.ssert_called_once_with(fake.SHARE_NAME) 

1163 self.assertEqual(0, mock_warning_log.call_count) 

1164 

1165 def test_wait_for_mount_replica_timeout(self): 

1166 

1167 mock_client = mock.Mock() 

1168 self.mock_object(time, 'sleep') 

1169 mock_warning_log = self.mock_object(data_motion.LOG, 'warning') 

1170 undergoing_snapmirror = ( 

1171 'The volume is undergoing a snapmirror initialize.') 

1172 na_api_error = netapp_api.NaApiError(code=netapp_api.EAPIERROR, 

1173 message=undergoing_snapmirror) 

1174 mock_client.mount_volume.side_effect = na_api_error 

1175 

1176 self.assertRaises(exception.NetAppException, 

1177 self.dm_session.wait_for_mount_replica, 

1178 mock_client, fake.SHARE_NAME, timeout=30) 

1179 

1180 self.assertEqual(3, mock_client.mount_volume.call_count) 

1181 self.assertEqual(3, mock_warning_log.call_count) 

1182 

1183 def test_wait_for_mount_replica_api_not_found(self): 

1184 

1185 mock_client = mock.Mock() 

1186 self.mock_object(time, 'sleep') 

1187 mock_warning_log = self.mock_object(data_motion.LOG, 'warning') 

1188 na_api_error = netapp_api.NaApiError(code=netapp_api.EOBJECTNOTFOUND) 

1189 mock_client.mount_volume.side_effect = na_api_error 

1190 

1191 self.assertRaises(exception.NetAppException, 

1192 self.dm_session.wait_for_mount_replica, 

1193 mock_client, fake.SHARE_NAME, timeout=30) 

1194 

1195 mock_client.mount_volume.assert_called_once_with(fake.SHARE_NAME) 

1196 mock_warning_log.assert_not_called() 

1197 

1198 @ddt.data(mock.Mock(), 

1199 mock.Mock(side_effect=netapp_api.NaApiError( 

1200 code=netapp_api.EOBJECTNOTFOUND))) 

1201 def test_wait_for_snapmirror_release_vol(self, release_snapmirror_ret): 

1202 src_mock_client = mock.Mock() 

1203 get_snapmirrors_mock = self.mock_object( 

1204 src_mock_client, 'get_snapmirror_destinations', 

1205 mock.Mock(side_effect=[['fake_snapmirror'], []])) 

1206 self.mock_object(src_mock_client, 'release_snapmirror_vol', 

1207 release_snapmirror_ret) 

1208 

1209 self.dm_session.wait_for_snapmirror_release_vol(fake.VSERVER1, 

1210 fake.VSERVER2, 

1211 fake.SHARE_NAME, 

1212 fake.SHARE_NAME2, 

1213 False, 

1214 src_mock_client, 

1215 timeout=20) 

1216 get_snapmirrors_mock.assert_has_calls([ 

1217 mock.call(source_vserver=fake.VSERVER1, 

1218 dest_vserver=fake.VSERVER2, 

1219 source_volume=fake.SHARE_NAME, 

1220 dest_volume=fake.SHARE_NAME2), 

1221 mock.call(source_vserver=fake.VSERVER1, 

1222 dest_vserver=fake.VSERVER2, 

1223 source_volume=fake.SHARE_NAME, 

1224 dest_volume=fake.SHARE_NAME2)]) 

1225 src_mock_client.release_snapmirror_vol.assert_called_once_with( 

1226 fake.VSERVER1, fake.SHARE_NAME, fake.VSERVER2, fake.SHARE_NAME2, 

1227 relationship_info_only=False) 

1228 

1229 def test_wait_for_snapmirror_release_vol_timeout(self): 

1230 src_mock_client = mock.Mock() 

1231 get_snapmirrors_mock = self.mock_object( 

1232 src_mock_client, 'get_snapmirror_destinations', 

1233 mock.Mock(side_effect=[['fake_snapmirror']])) 

1234 self.mock_object(src_mock_client, 'release_snapmirror_vol') 

1235 

1236 self.assertRaises(exception.NetAppException, 

1237 self.dm_session.wait_for_snapmirror_release_vol, 

1238 fake.VSERVER1, fake.VSERVER2, fake.SHARE_NAME, 

1239 fake.SHARE_NAME2, False, src_mock_client, 

1240 timeout=10) 

1241 

1242 get_snapmirrors_mock.assert_has_calls([ 

1243 mock.call(source_vserver=fake.VSERVER1, 

1244 dest_vserver=fake.VSERVER2, 

1245 source_volume=fake.SHARE_NAME, 

1246 dest_volume=fake.SHARE_NAME2)]) 

1247 src_mock_client.release_snapmirror_vol.assert_called_once_with( 

1248 fake.VSERVER1, fake.SHARE_NAME, fake.VSERVER2, fake.SHARE_NAME2, 

1249 relationship_info_only=False) 

1250 

1251 @ddt.data([{'id': 'src_share'}, {'id': 'dst_share'}], 

1252 [{'id': 'dst_share'}]) 

1253 def test_cleanup_previous_snapmirror_relationships(self, replica_list): 

1254 mock_src_client = mock.Mock() 

1255 src_backend_info = ('src_share', 'src_vserver', 'src_backend') 

1256 dst_backend_info = ('dst_share', 'dst_vserver', 'dst_backend') 

1257 self.mock_object(self.dm_session, 'get_backend_info_for_share', 

1258 mock.Mock(side_effect=[src_backend_info, 

1259 dst_backend_info])) 

1260 self.mock_object(data_motion, 'get_client_for_backend', 

1261 mock.Mock(return_value=mock_src_client)) 

1262 self.mock_object(mock_src_client, 'release_snapmirror_vol') 

1263 

1264 result = self.dm_session.cleanup_previous_snapmirror_relationships( 

1265 {'id': 'src_share'}, replica_list) 

1266 

1267 data_motion.get_client_for_backend.assert_called_once_with( 

1268 'src_backend', vserver_name='src_vserver') 

1269 self.dm_session.get_backend_info_for_share.assert_has_calls([ 

1270 mock.call({'id': 'src_share'}), 

1271 mock.call({'id': 'dst_share'}) 

1272 ]) 

1273 mock_src_client.release_snapmirror_vol.assert_called_once_with( 

1274 'src_vserver', 'src_share', 'dst_vserver', 'dst_share') 

1275 

1276 self.assertIsNone(result) 

1277 

1278 @ddt.data(netapp_api.NaApiError(), 

1279 netapp_api.NaApiError(code=netapp_api.EOBJECTNOTFOUND), 

1280 netapp_api.NaApiError(code=netapp_api.ESOURCE_IS_DIFFERENT), 

1281 netapp_api.NaApiError(code='some_random_code', 

1282 message="(entry doesn't exist)"), 

1283 netapp_api.NaApiError(code='some_random_code', 

1284 message='(actually, entry does exist!)')) 

1285 def test_cleanup_previous_snapmirror_relationships_does_not_exist( 

1286 self, release_exception): 

1287 mock_src_client = mock.Mock() 

1288 self.mock_object(self.dm_session, 'get_backend_info_for_share', 

1289 mock.Mock(return_value=( 

1290 mock.Mock(), mock.Mock(), mock.Mock()))) 

1291 self.mock_object(data_motion, 'get_client_for_backend', 

1292 mock.Mock(return_value=mock_src_client)) 

1293 self.mock_object(mock_src_client, 'release_snapmirror_vol', 

1294 mock.Mock(side_effect=release_exception)) 

1295 

1296 replica = {'id': 'src_share'} 

1297 replica_list = [replica, {'id': 'dst_share'}] 

1298 

1299 result = self.dm_session.cleanup_previous_snapmirror_relationships( 

1300 replica, replica_list) 

1301 

1302 mock_src_client.release_snapmirror_vol.assert_called() 

1303 self.assertIsNone(result) 

1304 

1305 def test_get_most_available_aggr_of_vserver(self): 

1306 vserver_client = mock.Mock() 

1307 aggr_space_attr = {fake.AGGREGATE: {'available': 5678}, 

1308 'aggr2': {'available': 2024}} 

1309 self.mock_object(vserver_client, 

1310 'get_vserver_aggregate_capacities', 

1311 mock.Mock(return_value=aggr_space_attr)) 

1312 result = self.dm_session.get_most_available_aggr_of_vserver( 

1313 vserver_client) 

1314 self.assertEqual(result, fake.AGGREGATE) 

1315 

1316 def test_initialize_and_wait_snapmirror_vol(self): 

1317 vserver_client = mock.Mock() 

1318 snapmirror_info = [{'source-vserver': fake.VSERVER1, 

1319 'source-volume': "fake_source_vol", 

1320 'destination-vserver': fake.VSERVER2, 

1321 'destination-volume': "fake_des_vol", 

1322 'relationship-status': "idle"}] 

1323 self.mock_object(vserver_client, 

1324 'get_snapmirrors', 

1325 mock.Mock(return_value=snapmirror_info)) 

1326 

1327 (self.dm_session. 

1328 initialize_and_wait_snapmirror_vol(vserver_client, 

1329 fake.VSERVER1, 

1330 fake.FLEXVOL_NAME, 

1331 fake.VSERVER2, 

1332 fake.FLEXVOL_NAME_1, 

1333 source_snapshot=None, 

1334 transfer_priority=None, 

1335 timeout=300)) 

1336 (vserver_client.initialize_snapmirror_vol. 

1337 assert_called_once_with(mock.ANY, 

1338 mock.ANY, 

1339 mock.ANY, 

1340 mock.ANY, 

1341 source_snapshot=mock.ANY, 

1342 transfer_priority=mock.ANY, 

1343 ))