Coverage for manila/tests/share/drivers/ganesha/test_manager.py: 99%

601 statements  

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

1# Copyright (c) 2014 Red Hat, Inc. 

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 

16import copy 

17import io 

18import re 

19from unittest import mock 

20 

21import ddt 

22from oslo_serialization import jsonutils 

23 

24from manila import exception 

25from manila.share.drivers.ganesha import manager 

26from manila import test 

27from manila import utils 

28 

29test_export_id = 101 

30test_name = 'fakefile' 

31test_path = '/fakedir0/export.d/fakefile.conf' 

32test_tmp_path = '/fakedir0/export.d/fakefile.conf.RANDOM' 

33test_ganesha_cnf = """EXPORT { 

34 Export_Id = 101; 

35 CLIENT { 

36 Clients = ip1; 

37 Access_Level = ro; 

38 } 

39 CLIENT { 

40 Clients = ip2; 

41 Access_Level = rw; 

42 } 

43}""" 

44test_dict_unicode = { 

45 u'EXPORT': { 

46 u'Export_Id': 101, 

47 u'CLIENT': [ 

48 {u'Clients': u"ip1", u'Access_Level': u'ro'}, 

49 {u'Clients': u"ip2", u'Access_Level': u'rw'}] 

50 } 

51} 

52test_dict_str = { 

53 'EXPORT': { 

54 'Export_Id': 101, 

55 'CLIENT': [ 

56 {'Clients': 'ip1', 'Access_Level': 'ro'}, 

57 {'Clients': 'ip2', 'Access_Level': 'rw'}] 

58 } 

59} 

60 

61manager_fake_kwargs = { 

62 'ganesha_config_path': '/fakedir0/fakeconfig', 

63 'ganesha_db_path': '/fakedir1/fake.db', 

64 'ganesha_export_dir': '/fakedir0/export.d', 

65 'ganesha_service_name': 'ganesha.fakeservice' 

66} 

67 

68 

69class MockRadosModule(object): 

70 """Mocked up version of Ceph's RADOS module.""" 

71 

72 class ObjectNotFound(Exception): 

73 pass 

74 

75 class OSError(Exception): 

76 pass 

77 

78 class WriteOpCtx(): 

79 

80 def __enter__(self): 

81 return self 

82 

83 def __exit__(self, type, msg, traceback): 

84 pass 

85 

86 def write_full(self, bytes_to_write): 

87 pass 

88 

89 

90@ddt.ddt 

91class MiscTests(test.TestCase): 

92 

93 @ddt.data({'import_exc': None}, 

94 {'import_exc': ImportError}) 

95 @ddt.unpack 

96 def test_setup_rados(self, import_exc): 

97 manager.rados = None 

98 with mock.patch.object( 

99 manager.importutils, 

100 'import_module', 

101 side_effect=import_exc) as mock_import_module: 

102 if import_exc: 

103 self.assertRaises( 

104 exception.ShareBackendException, manager.setup_rados) 

105 else: 

106 manager.setup_rados() 

107 self.assertEqual(mock_import_module.return_value, 

108 manager.rados) 

109 mock_import_module.assert_called_once_with('rados') 

110 

111 

112class GaneshaConfigTests(test.TestCase): 

113 """Tests Ganesha config file format convertor functions.""" 

114 

115 ref_ganesha_cnf = """EXPORT { 

116 CLIENT { 

117 Clients = ip1; 

118 Access_Level = "ro"; 

119 } 

120 CLIENT { 

121 Clients = ip2; 

122 Access_Level = "rw"; 

123 } 

124 Export_Id = 101; 

125}""" 

126 

127 @staticmethod 

128 def conf_mangle(*confs): 

129 """A "mangler" for the conf format. 

130 

131 Its purpose is to transform conf data in a way so that semantically 

132 equivalent confs yield identical results. Besides this objective 

133 criteria, we seek a good trade-off between the following 

134 requirements: 

135 - low lossiness; 

136 - low code complexity. 

137 """ 

138 def _conf_mangle(conf): 

139 # split to expressions by the delimiter ";" 

140 # (braces are forced to be treated as expressions 

141 # by sandwiching them in ";"-s) 

142 conf = re.sub(r'[{}]', r';\g<0>;', conf).split(';') 

143 # whitespace-split expressions to tokens with 

144 # (equality is forced to be treated as token by 

145 # sandwiching in space) 

146 conf = map(lambda line: line.replace("=", " = ").split(), conf) 

147 # get rid of by-product empty lists (derived from superflouous 

148 # ";"-s that might have crept in due to "sandwiching") 

149 conf = map(lambda x: x, conf) 

150 # handle the non-deterministic order of confs 

151 conf = list(conf) 

152 conf.sort() 

153 return conf 

154 

155 return (_conf_mangle(conf) for conf in confs) 

156 

157 def test_conf2json(self): 

158 test_ganesha_cnf_with_comment = """EXPORT { 

159# fake_export_block 

160 Export_Id = 101; 

161 CLIENT { 

162 Clients = ip1; 

163 } 

164}""" 

165 result_dict_unicode = { 

166 u'EXPORT': { 

167 u'CLIENT': {u'Clients': u'ip1'}, 

168 u'Export_Id': 101 

169 } 

170 } 

171 ret = manager._conf2json(test_ganesha_cnf_with_comment) 

172 self.assertEqual(result_dict_unicode, jsonutils.loads(ret)) 

173 

174 def test_parseconf_ganesha_cnf_input(self): 

175 ret = manager.parseconf(test_ganesha_cnf) 

176 self.assertEqual(test_dict_unicode, ret) 

177 

178 def test_parseconf_json_input(self): 

179 ret = manager.parseconf(jsonutils.dumps(test_dict_str)) 

180 self.assertEqual(test_dict_unicode, ret) 

181 

182 def test_dump_to_conf(self): 

183 ganesha_cnf = io.StringIO() 

184 manager._dump_to_conf(test_dict_str, ganesha_cnf) 

185 self.assertEqual(*self.conf_mangle(self.ref_ganesha_cnf, 

186 ganesha_cnf.getvalue())) 

187 

188 def test_mkconf(self): 

189 ganesha_cnf = manager.mkconf(test_dict_str) 

190 self.assertEqual(*self.conf_mangle(self.ref_ganesha_cnf, 

191 ganesha_cnf)) 

192 

193 

194@ddt.ddt 

195class GaneshaManagerTestCase(test.TestCase): 

196 """Tests GaneshaManager.""" 

197 

198 def instantiate_ganesha_manager(self, *args, **kwargs): 

199 ganesha_rados_store_enable = kwargs.get('ganesha_rados_store_enable', 

200 False) 

201 if ganesha_rados_store_enable: 

202 with mock.patch.object( 

203 manager.GaneshaManager, 

204 '_get_rados_object') as self.mock_get_rados_object: 

205 return manager.GaneshaManager(*args, **kwargs) 

206 else: 

207 with mock.patch.object( 

208 manager.GaneshaManager, 

209 'get_export_id', 

210 return_value=100) as self.mock_get_export_id: 

211 return manager.GaneshaManager(*args, **kwargs) 

212 

213 def setUp(self): 

214 super(GaneshaManagerTestCase, self).setUp() 

215 self._execute = mock.Mock(return_value=('', '')) 

216 self._rados_client = mock.Mock() 

217 self._manager = self.instantiate_ganesha_manager( 

218 self._execute, 'faketag', 

219 rados_client=self._rados_client, 

220 **manager_fake_kwargs) 

221 self._setup_rados = mock.Mock() 

222 self._execute2 = mock.Mock(return_value=('', '')) 

223 self.mock_object(manager, 'rados', MockRadosModule) 

224 self.mock_object(manager, 'setup_rados', self._setup_rados) 

225 fake_kwargs = copy.copy(manager_fake_kwargs) 

226 fake_kwargs.update( 

227 ganesha_rados_store_enable=True, 

228 ganesha_rados_store_pool_name='fakepool', 

229 ganesha_rados_export_counter='fakecounter', 

230 ganesha_rados_export_index='fakeindex', 

231 rados_client=self._rados_client 

232 ) 

233 self._manager_with_rados_store = self.instantiate_ganesha_manager( 

234 self._execute2, 'faketag', **fake_kwargs) 

235 self.mock_object(utils, 'synchronized', 

236 mock.Mock(return_value=lambda f: f)) 

237 

238 def test_init(self): 

239 self.mock_object(self._manager, 'reset_exports') 

240 self.mock_object(self._manager, 'restart_service') 

241 self.assertEqual('/fakedir0/fakeconfig', 

242 self._manager.ganesha_config_path) 

243 self.assertEqual('faketag', self._manager.tag) 

244 self.assertEqual('/fakedir0/export.d', 

245 self._manager.ganesha_export_dir) 

246 self.assertEqual('/fakedir1/fake.db', self._manager.ganesha_db_path) 

247 self.assertEqual('ganesha.fakeservice', self._manager.ganesha_service) 

248 self.assertEqual( 

249 [mock.call('mkdir', '-p', self._manager.ganesha_export_dir), 

250 mock.call('mkdir', '-p', '/fakedir1'), 

251 mock.call('sqlite3', self._manager.ganesha_db_path, 

252 'create table ganesha(key varchar(20) primary key, ' 

253 'value int); insert into ganesha values("exportid", ' 

254 '100);', run_as_root=False, check_exit_code=False)], 

255 self._execute.call_args_list) 

256 self.mock_get_export_id.assert_called_once_with(bump=False) 

257 

258 def test_init_execute_error_log_message(self): 

259 fake_args = ('foo', 'bar') 

260 

261 def raise_exception(*args, **kwargs): 

262 if args == fake_args: 

263 raise exception.GaneshaCommandFailure() 

264 

265 test_execute = mock.Mock(side_effect=raise_exception) 

266 self.mock_object(manager.LOG, 'error') 

267 test_manager = self.instantiate_ganesha_manager( 

268 test_execute, 'faketag', **manager_fake_kwargs) 

269 self.assertRaises( 

270 exception.GaneshaCommandFailure, 

271 test_manager.execute, 

272 *fake_args, message='fakemsg') 

273 manager.LOG.error.assert_called_once_with( 

274 mock.ANY, {'tag': 'faketag', 'msg': 'fakemsg'}) 

275 

276 def test_init_execute_error_no_log_message(self): 

277 fake_args = ('foo', 'bar') 

278 

279 def raise_exception(*args, **kwargs): 

280 if args == fake_args: 

281 raise exception.GaneshaCommandFailure() 

282 

283 test_execute = mock.Mock(side_effect=raise_exception) 

284 self.mock_object(manager.LOG, 'error') 

285 test_manager = self.instantiate_ganesha_manager( 

286 test_execute, 'faketag', **manager_fake_kwargs) 

287 self.assertRaises( 

288 exception.GaneshaCommandFailure, 

289 test_manager.execute, 

290 *fake_args, message='fakemsg', makelog=False) 

291 self.assertFalse(manager.LOG.error.called) 

292 

293 @ddt.data(False, True) 

294 def test_init_with_rados_store_and_export_counter_exists( 

295 self, counter_exists): 

296 fake_execute = mock.Mock(return_value=('', '')) 

297 fake_kwargs = copy.copy(manager_fake_kwargs) 

298 fake_kwargs.update( 

299 ganesha_rados_store_enable=True, 

300 ganesha_rados_store_pool_name='fakepool', 

301 ganesha_rados_export_counter='fakecounter', 

302 ganesha_rados_export_index='fakeindex', 

303 rados_client=self._rados_client 

304 ) 

305 if counter_exists: 

306 self.mock_object( 

307 manager.GaneshaManager, '_get_rados_object', mock.Mock()) 

308 else: 

309 self.mock_object( 

310 manager.GaneshaManager, '_get_rados_object', 

311 mock.Mock(side_effect=MockRadosModule.ObjectNotFound)) 

312 self.mock_object(manager.GaneshaManager, '_put_rados_object') 

313 

314 test_mgr = manager.GaneshaManager( 

315 fake_execute, 'faketag', **fake_kwargs) 

316 

317 self.assertEqual('/fakedir0/fakeconfig', test_mgr.ganesha_config_path) 

318 self.assertEqual('faketag', test_mgr.tag) 

319 self.assertEqual('/fakedir0/export.d', test_mgr.ganesha_export_dir) 

320 self.assertEqual('ganesha.fakeservice', test_mgr.ganesha_service) 

321 fake_execute.assert_called_once_with( 

322 'mkdir', '-p', '/fakedir0/export.d') 

323 self.assertTrue(test_mgr.ganesha_rados_store_enable) 

324 self.assertEqual('fakepool', test_mgr.ganesha_rados_store_pool_name) 

325 self.assertEqual('fakecounter', test_mgr.ganesha_rados_export_counter) 

326 self.assertEqual('fakeindex', test_mgr.ganesha_rados_export_index) 

327 self.assertEqual(self._rados_client, test_mgr.rados_client) 

328 self._setup_rados.assert_called_with() 

329 test_mgr._get_rados_object.assert_called_once_with('fakecounter') 

330 if counter_exists: 

331 self.assertFalse(test_mgr._put_rados_object.called) 

332 else: 

333 test_mgr._put_rados_object.assert_called_once_with( 

334 'fakecounter', str(1000)) 

335 

336 def test_ganesha_export_dir(self): 

337 self.assertEqual( 

338 '/fakedir0/export.d', self._manager.ganesha_export_dir) 

339 

340 def test_getpath(self): 

341 self.assertEqual( 

342 '/fakedir0/export.d/fakefile.conf', 

343 self._manager._getpath('fakefile')) 

344 

345 def test_get_export_rados_object_name(self): 

346 self.assertEqual( 

347 'ganesha-export-fakeobj', 

348 self._manager._get_export_rados_object_name('fakeobj')) 

349 

350 def test_write_tmp_conf_file(self): 

351 self.mock_object(manager.shlex, 'quote', 

352 mock.Mock(side_effect=['fakedata', 

353 test_tmp_path])) 

354 test_args = [ 

355 ('mktemp', '-p', '/fakedir0/export.d', '-t', 

356 'fakefile.conf.XXXXXX'), 

357 ('sh', '-c', 'echo fakedata > %s' % test_tmp_path)] 

358 test_kwargs = { 

359 'message': 'writing %s' % test_tmp_path 

360 } 

361 

362 def return_tmpfile(*args, **kwargs): 

363 if args == test_args[0]: 

364 return (test_tmp_path + '\n', '') 

365 self.mock_object(self._manager, 'execute', 

366 mock.Mock(side_effect=return_tmpfile)) 

367 

368 ret = self._manager._write_tmp_conf_file(test_path, 'fakedata') 

369 

370 self._manager.execute.assert_has_calls([ 

371 mock.call(*test_args[0]), 

372 mock.call(*test_args[1], **test_kwargs)]) 

373 manager.shlex.quote.assert_has_calls([ 

374 mock.call('fakedata'), 

375 mock.call(test_tmp_path)]) 

376 self.assertEqual(test_tmp_path, ret) 

377 

378 @ddt.data(True, False) 

379 def test_write_conf_file_with_mv_error(self, mv_error): 

380 test_data = 'fakedata' 

381 test_args = [ 

382 ('mv', test_tmp_path, test_path), 

383 ('rm', test_tmp_path)] 

384 self.mock_object(self._manager, '_getpath', 

385 mock.Mock(return_value=test_path)) 

386 self.mock_object(self._manager, '_write_tmp_conf_file', 

387 mock.Mock(return_value=test_tmp_path)) 

388 

389 def mock_return(*args, **kwargs): 

390 if args == test_args[0]: 

391 if mv_error: 

392 raise exception.ProcessExecutionError() 

393 else: 

394 return ('', '') 

395 

396 self.mock_object(self._manager, 'execute', 

397 mock.Mock(side_effect=mock_return)) 

398 

399 if mv_error: 

400 self.assertRaises( 

401 exception.ProcessExecutionError, 

402 self._manager._write_conf_file, test_name, test_data) 

403 else: 

404 ret = self._manager._write_conf_file(test_name, test_data) 

405 

406 self._manager._getpath.assert_called_once_with(test_name) 

407 self._manager._write_tmp_conf_file.assert_called_once_with( 

408 test_path, test_data) 

409 if mv_error: 

410 self._manager.execute.assert_has_calls([ 

411 mock.call(*test_args[0]), 

412 mock.call(*test_args[1])]) 

413 else: 

414 self._manager.execute.assert_has_calls([ 

415 mock.call(*test_args[0])]) 

416 self.assertEqual(test_path, ret) 

417 

418 def test_mkindex(self): 

419 test_ls_output = 'INDEX.conf\nfakefile.conf\nfakefile.txt' 

420 test_index = '%include /fakedir0/export.d/fakefile.conf\n' 

421 self.mock_object(self._manager, 'execute', 

422 mock.Mock(return_value=(test_ls_output, ''))) 

423 self.mock_object(self._manager, '_write_conf_file') 

424 ret = self._manager._mkindex() 

425 self._manager.execute.assert_called_once_with( 

426 'ls', '/fakedir0/export.d', run_as_root=False) 

427 self._manager._write_conf_file.assert_called_once_with( 

428 'INDEX', test_index) 

429 self.assertIsNone(ret) 

430 

431 def test_read_export_rados_object(self): 

432 self.mock_object(self._manager_with_rados_store, 

433 '_get_export_rados_object_name', 

434 mock.Mock(return_value='fakeobj')) 

435 self.mock_object(self._manager_with_rados_store, '_get_rados_object', 

436 mock.Mock(return_value=test_ganesha_cnf)) 

437 self.mock_object(manager, 'parseconf', 

438 mock.Mock(return_value=test_dict_unicode)) 

439 

440 ret = self._manager_with_rados_store._read_export_rados_object( 

441 test_name) 

442 

443 (self._manager_with_rados_store._get_export_rados_object_name. 

444 assert_called_once_with(test_name)) 

445 (self._manager_with_rados_store._get_rados_object. 

446 assert_called_once_with('fakeobj')) 

447 manager.parseconf.assert_called_once_with(test_ganesha_cnf) 

448 self.assertEqual(test_dict_unicode, ret) 

449 

450 def test_read_export_file(self): 

451 test_args = ('cat', test_path) 

452 test_kwargs = {'message': 'reading export fakefile'} 

453 self.mock_object(self._manager, '_getpath', 

454 mock.Mock(return_value=test_path)) 

455 self.mock_object(self._manager, 'execute', 

456 mock.Mock(return_value=(test_ganesha_cnf,))) 

457 self.mock_object(manager, 'parseconf', 

458 mock.Mock(return_value=test_dict_unicode)) 

459 ret = self._manager._read_export_file(test_name) 

460 self._manager._getpath.assert_called_once_with(test_name) 

461 self._manager.execute.assert_called_once_with( 

462 *test_args, **test_kwargs) 

463 manager.parseconf.assert_called_once_with(test_ganesha_cnf) 

464 self.assertEqual(test_dict_unicode, ret) 

465 

466 @ddt.data(False, True) 

467 def test_read_export_with_rados_store(self, rados_store_enable): 

468 self._manager.ganesha_rados_store_enable = rados_store_enable 

469 self.mock_object(self._manager, '_read_export_file', 

470 mock.Mock(return_value=test_dict_unicode)) 

471 self.mock_object(self._manager, '_read_export_rados_object', 

472 mock.Mock(return_value=test_dict_unicode)) 

473 

474 ret = self._manager._read_export(test_name) 

475 

476 if rados_store_enable: 

477 self._manager._read_export_rados_object.assert_called_once_with( 

478 test_name) 

479 self.assertFalse(self._manager._read_export_file.called) 

480 else: 

481 self._manager._read_export_file.assert_called_once_with(test_name) 

482 self.assertFalse(self._manager._read_export_rados_object.called) 

483 self.assertEqual(test_dict_unicode, ret) 

484 

485 @ddt.data(True, False) 

486 def test_check_export_rados_object_exists(self, exists): 

487 self.mock_object( 

488 self._manager_with_rados_store, 

489 '_get_export_rados_object_name', mock.Mock(return_value='fakeobj')) 

490 if exists: 

491 self.mock_object( 

492 self._manager_with_rados_store, '_get_rados_object') 

493 else: 

494 self.mock_object( 

495 self._manager_with_rados_store, '_get_rados_object', 

496 mock.Mock(side_effect=MockRadosModule.ObjectNotFound)) 

497 

498 ret = self._manager_with_rados_store._check_export_rados_object_exists( 

499 test_name) 

500 

501 (self._manager_with_rados_store._get_export_rados_object_name. 

502 assert_called_once_with(test_name)) 

503 (self._manager_with_rados_store._get_rados_object. 

504 assert_called_once_with('fakeobj')) 

505 if exists: 

506 self.assertTrue(ret) 

507 else: 

508 self.assertFalse(ret) 

509 

510 def test_check_file_exists(self): 

511 self.mock_object(self._manager, 'execute', 

512 mock.Mock(return_value=(test_ganesha_cnf,))) 

513 

514 ret = self._manager._check_file_exists(test_path) 

515 

516 self._manager.execute.assert_called_once_with( 

517 'test', '-f', test_path, makelog=False, run_as_root=False) 

518 self.assertTrue(ret) 

519 

520 @ddt.data(1, 4) 

521 def test_check_file_exists_error(self, exit_code): 

522 self.mock_object( 

523 self._manager, 'execute', 

524 mock.Mock(side_effect=exception.GaneshaCommandFailure( 

525 exit_code=exit_code)) 

526 ) 

527 

528 if exit_code == 1: 

529 ret = self._manager._check_file_exists(test_path) 

530 self.assertFalse(ret) 

531 else: 

532 self.assertRaises(exception.GaneshaCommandFailure, 

533 self._manager._check_file_exists, 

534 test_path) 

535 

536 self._manager.execute.assert_called_once_with( 

537 'test', '-f', test_path, makelog=False, run_as_root=False) 

538 

539 def test_check_export_file_exists(self): 

540 self.mock_object(self._manager, '_getpath', 

541 mock.Mock(return_value=test_path)) 

542 self.mock_object(self._manager, '_check_file_exists', 

543 mock.Mock(return_value=True)) 

544 

545 ret = self._manager._check_export_file_exists(test_name) 

546 

547 self._manager._getpath.assert_called_once_with(test_name) 

548 self._manager._check_file_exists.assert_called_once_with(test_path) 

549 self.assertTrue(ret) 

550 

551 @ddt.data(False, True) 

552 def test_check_export_exists_with_rados_store(self, rados_store_enable): 

553 self._manager.ganesha_rados_store_enable = rados_store_enable 

554 self.mock_object(self._manager, '_check_export_file_exists', 

555 mock.Mock(return_value=True)) 

556 self.mock_object(self._manager, '_check_export_rados_object_exists', 

557 mock.Mock(return_value=True)) 

558 

559 ret = self._manager.check_export_exists(test_name) 

560 

561 if rados_store_enable: 

562 (self._manager._check_export_rados_object_exists. 

563 assert_called_once_with(test_name)) 

564 self.assertFalse(self._manager._check_export_file_exists.called) 

565 else: 

566 self._manager._check_export_file_exists.assert_called_once_with( 

567 test_name) 

568 self.assertFalse( 

569 self._manager._check_export_rados_object_exists.called) 

570 self.assertTrue(ret) 

571 

572 def test_write_export_rados_object(self): 

573 self.mock_object(self._manager, '_get_export_rados_object_name', 

574 mock.Mock(return_value='fakeobj')) 

575 self.mock_object(self._manager, '_put_rados_object') 

576 self.mock_object(self._manager, '_getpath', 

577 mock.Mock(return_value=test_path)) 

578 self.mock_object(self._manager, '_write_tmp_conf_file', 

579 mock.Mock(return_value=test_tmp_path)) 

580 

581 ret = self._manager._write_export_rados_object(test_name, 'fakedata') 

582 

583 self._manager._get_export_rados_object_name.assert_called_once_with( 

584 test_name) 

585 self._manager._put_rados_object.assert_called_once_with( 

586 'fakeobj', 'fakedata') 

587 self._manager._getpath.assert_called_once_with(test_name) 

588 self._manager._write_tmp_conf_file.assert_called_once_with( 

589 test_path, 'fakedata') 

590 self.assertEqual(test_tmp_path, ret) 

591 

592 @ddt.data(True, False) 

593 def test_write_export_with_rados_store(self, rados_store_enable): 

594 self._manager.ganesha_rados_store_enable = rados_store_enable 

595 self.mock_object(manager, 'mkconf', 

596 mock.Mock(return_value=test_ganesha_cnf)) 

597 self.mock_object(self._manager, '_write_conf_file', 

598 mock.Mock(return_value=test_path)) 

599 self.mock_object(self._manager, '_write_export_rados_object', 

600 mock.Mock(return_value=test_path)) 

601 

602 ret = self._manager._write_export(test_name, test_dict_str) 

603 

604 manager.mkconf.assert_called_once_with(test_dict_str) 

605 if rados_store_enable: 

606 self._manager._write_export_rados_object.assert_called_once_with( 

607 test_name, test_ganesha_cnf) 

608 self.assertFalse(self._manager._write_conf_file.called) 

609 else: 

610 self._manager._write_conf_file.assert_called_once_with( 

611 test_name, test_ganesha_cnf) 

612 self.assertFalse(self._manager._write_export_rados_object.called) 

613 self.assertEqual(test_path, ret) 

614 

615 def test_write_export_error_incomplete_export_block(self): 

616 test_errordict = { 

617 u'EXPORT': { 

618 u'Export_Id': '@config', 

619 u'CLIENT': {u'Clients': u"'ip1','ip2'"} 

620 } 

621 } 

622 self.mock_object(manager, 'mkconf', 

623 mock.Mock(return_value=test_ganesha_cnf)) 

624 self.mock_object(self._manager, '_write_conf_file', 

625 mock.Mock(return_value=test_path)) 

626 

627 self.assertRaises(exception.InvalidParameterValue, 

628 self._manager._write_export, 

629 test_name, test_errordict) 

630 

631 self.assertFalse(manager.mkconf.called) 

632 self.assertFalse(self._manager._write_conf_file.called) 

633 

634 def test_rm_file(self): 

635 self.mock_object(self._manager, 'execute', 

636 mock.Mock(return_value=('', ''))) 

637 ret = self._manager._rm_export_file(test_name) 

638 

639 self._manager.execute.assert_called_once_with('rm', '-f', test_path) 

640 self.assertIsNone(ret) 

641 

642 def test_rm_export_file(self): 

643 self.mock_object(self._manager, '_getpath', 

644 mock.Mock(return_value=test_path)) 

645 self.mock_object(self._manager, '_rm_file') 

646 

647 ret = self._manager._rm_export_file(test_name) 

648 

649 self._manager._getpath.assert_called_once_with(test_name) 

650 self._manager._rm_file.assert_called_once_with(test_path) 

651 self.assertIsNone(ret) 

652 

653 def test_rm_export_rados_object(self): 

654 self.mock_object(self._manager_with_rados_store, 

655 '_get_export_rados_object_name', 

656 mock.Mock(return_value='fakeobj')) 

657 self.mock_object(self._manager_with_rados_store, 

658 '_delete_rados_object') 

659 

660 ret = self._manager_with_rados_store._rm_export_rados_object( 

661 test_name) 

662 

663 (self._manager_with_rados_store._get_export_rados_object_name. 

664 assert_called_once_with(test_name)) 

665 (self._manager_with_rados_store._delete_rados_object. 

666 assert_called_once_with('fakeobj')) 

667 self.assertIsNone(ret) 

668 

669 def test_dbus_send_ganesha(self): 

670 test_args = ('arg1', 'arg2') 

671 test_kwargs = {'key': 'value'} 

672 self.mock_object(self._manager, 'execute', 

673 mock.Mock(return_value=('', ''))) 

674 ret = self._manager._dbus_send_ganesha('fakemethod', *test_args, 

675 **test_kwargs) 

676 self._manager.execute.assert_called_once_with( 

677 'dbus-send', '--print-reply', '--system', 

678 '--dest=org.ganesha.nfsd', '/org/ganesha/nfsd/ExportMgr', 

679 'org.ganesha.nfsd.exportmgr.fakemethod', 

680 *test_args, message='dbus call exportmgr.fakemethod', 

681 **test_kwargs) 

682 self.assertIsNone(ret) 

683 

684 def test_remove_export_dbus(self): 

685 self.mock_object(self._manager, '_dbus_send_ganesha') 

686 ret = self._manager._remove_export_dbus(test_export_id) 

687 self._manager._dbus_send_ganesha.assert_called_once_with( 

688 'RemoveExport', 'uint16:101') 

689 self.assertIsNone(ret) 

690 

691 @ddt.data('', 

692 '%url rados://fakepool/fakeobj2') 

693 def test_add_rados_object_url_to_index_with_index_data( 

694 self, index_data): 

695 self.mock_object( 

696 self._manager_with_rados_store, '_get_rados_object', 

697 mock.Mock(return_value=index_data)) 

698 self.mock_object( 

699 self._manager_with_rados_store, '_get_export_rados_object_name', 

700 mock.Mock(return_value='fakeobj1')) 

701 self.mock_object( 

702 self._manager_with_rados_store, '_put_rados_object') 

703 

704 ret = (self._manager_with_rados_store. 

705 _add_rados_object_url_to_index('fakename')) 

706 

707 (self._manager_with_rados_store._get_rados_object. 

708 assert_called_once_with('fakeindex')) 

709 (self._manager_with_rados_store._get_export_rados_object_name. 

710 assert_called_once_with('fakename')) 

711 if index_data: 

712 urls = ('%url rados://fakepool/fakeobj2\n' 

713 '%url rados://fakepool/fakeobj1') 

714 else: 

715 urls = '%url rados://fakepool/fakeobj1' 

716 (self._manager_with_rados_store._put_rados_object. 

717 assert_called_once_with('fakeindex', urls)) 

718 self.assertIsNone(ret) 

719 

720 @ddt.data('', 

721 '%url rados://fakepool/fakeobj1\n' 

722 '%url rados://fakepool/fakeobj2') 

723 def test_remove_rados_object_url_from_index_with_index_data( 

724 self, index_data): 

725 self.mock_object( 

726 self._manager_with_rados_store, '_get_rados_object', 

727 mock.Mock(return_value=index_data)) 

728 self.mock_object( 

729 self._manager_with_rados_store, '_get_export_rados_object_name', 

730 mock.Mock(return_value='fakeobj1')) 

731 self.mock_object( 

732 self._manager_with_rados_store, '_put_rados_object') 

733 

734 ret = (self._manager_with_rados_store. 

735 _remove_rados_object_url_from_index('fakename')) 

736 

737 if index_data: 

738 (self._manager_with_rados_store._get_rados_object. 

739 assert_called_once_with('fakeindex')) 

740 (self._manager_with_rados_store._get_export_rados_object_name. 

741 assert_called_once_with('fakename')) 

742 urls = '%url rados://fakepool/fakeobj2' 

743 (self._manager_with_rados_store._put_rados_object. 

744 assert_called_once_with('fakeindex', urls)) 

745 else: 

746 (self._manager_with_rados_store._get_rados_object. 

747 assert_called_once_with('fakeindex')) 

748 self.assertFalse(self._manager_with_rados_store. 

749 _get_export_rados_object_name.called) 

750 self.assertFalse(self._manager_with_rados_store. 

751 _put_rados_object.called) 

752 self.assertIsNone(ret) 

753 

754 @ddt.data(False, True) 

755 def test_add_export_with_rados_store(self, rados_store_enable): 

756 self._manager.ganesha_rados_store_enable = rados_store_enable 

757 self.mock_object(self._manager, '_write_export', 

758 mock.Mock(return_value=test_path)) 

759 self.mock_object(self._manager, '_dbus_send_ganesha') 

760 self.mock_object(self._manager, '_rm_file') 

761 self.mock_object(self._manager, '_add_rados_object_url_to_index') 

762 self.mock_object(self._manager, '_mkindex') 

763 

764 ret = self._manager.add_export(test_name, test_dict_str) 

765 

766 self._manager._write_export.assert_called_once_with( 

767 test_name, test_dict_str) 

768 self._manager._dbus_send_ganesha.assert_called_once_with( 

769 'AddExport', 'string:' + test_path, 

770 'string:EXPORT(Export_Id=101)') 

771 if rados_store_enable: 

772 self._manager._rm_file.assert_called_once_with(test_path) 

773 self._manager._add_rados_object_url_to_index(test_name) 

774 self.assertFalse(self._manager._mkindex.called) 

775 else: 

776 self._manager._mkindex.assert_called_once_with() 

777 self.assertFalse(self._manager._rm_file.called) 

778 self.assertFalse( 

779 self._manager._add_rados_object_url_to_index.called) 

780 self.assertIsNone(ret) 

781 

782 def test_add_export_error_during_mkindex(self): 

783 self.mock_object(self._manager, '_write_export', 

784 mock.Mock(return_value=test_path)) 

785 self.mock_object(self._manager, '_dbus_send_ganesha') 

786 self.mock_object( 

787 self._manager, '_mkindex', 

788 mock.Mock(side_effect=exception.GaneshaCommandFailure)) 

789 self.mock_object(self._manager, '_rm_export_file') 

790 self.mock_object(self._manager, '_remove_export_dbus') 

791 

792 self.assertRaises(exception.GaneshaCommandFailure, 

793 self._manager.add_export, test_name, test_dict_str) 

794 

795 self._manager._write_export.assert_called_once_with( 

796 test_name, test_dict_str) 

797 self._manager._dbus_send_ganesha.assert_called_once_with( 

798 'AddExport', 'string:' + test_path, 

799 'string:EXPORT(Export_Id=101)') 

800 self._manager._mkindex.assert_called_once_with() 

801 self._manager._rm_export_file.assert_called_once_with(test_name) 

802 self._manager._remove_export_dbus.assert_called_once_with( 

803 test_export_id) 

804 

805 @ddt.data(True, False) 

806 def test_add_export_error_during_write_export_with_rados_store( 

807 self, rados_store_enable): 

808 self._manager.ganesha_rados_store_enable = rados_store_enable 

809 self.mock_object( 

810 self._manager, '_write_export', 

811 mock.Mock(side_effect=exception.GaneshaCommandFailure)) 

812 self.mock_object(self._manager, '_mkindex') 

813 

814 self.assertRaises(exception.GaneshaCommandFailure, 

815 self._manager.add_export, test_name, test_dict_str) 

816 

817 self._manager._write_export.assert_called_once_with( 

818 test_name, test_dict_str) 

819 if rados_store_enable: 

820 self.assertFalse(self._manager._mkindex.called) 

821 else: 

822 self._manager._mkindex.assert_called_once_with() 

823 

824 @ddt.data(True, False) 

825 def test_add_export_error_during_dbus_send_ganesha_with_rados_store( 

826 self, rados_store_enable): 

827 self._manager.ganesha_rados_store_enable = rados_store_enable 

828 self.mock_object(self._manager, '_write_export', 

829 mock.Mock(return_value=test_path)) 

830 self.mock_object( 

831 self._manager, '_dbus_send_ganesha', 

832 mock.Mock(side_effect=exception.GaneshaCommandFailure)) 

833 self.mock_object(self._manager, '_mkindex') 

834 self.mock_object(self._manager, '_rm_export_file') 

835 self.mock_object(self._manager, '_rm_export_rados_object') 

836 self.mock_object(self._manager, '_rm_file') 

837 self.mock_object(self._manager, '_remove_export_dbus') 

838 

839 self.assertRaises(exception.GaneshaCommandFailure, 

840 self._manager.add_export, test_name, test_dict_str) 

841 

842 self._manager._write_export.assert_called_once_with( 

843 test_name, test_dict_str) 

844 self._manager._dbus_send_ganesha.assert_called_once_with( 

845 'AddExport', 'string:' + test_path, 

846 'string:EXPORT(Export_Id=101)') 

847 if rados_store_enable: 

848 self._manager._rm_export_rados_object.assert_called_once_with( 

849 test_name) 

850 self._manager._rm_file.assert_called_once_with(test_path) 

851 self.assertFalse(self._manager._rm_export_file.called) 

852 self.assertFalse(self._manager._mkindex.called) 

853 else: 

854 self._manager._rm_export_file.assert_called_once_with(test_name) 

855 self._manager._mkindex.assert_called_once_with() 

856 self.assertFalse(self._manager._rm_export_rados_object.called) 

857 self.assertFalse(self._manager._rm_file.called) 

858 self.assertFalse(self._manager._remove_export_dbus.called) 

859 

860 @ddt.data(True, False) 

861 def test_update_export_with_rados_store(self, rados_store_enable): 

862 self._manager.ganesha_rados_store_enable = rados_store_enable 

863 confdict = { 

864 'EXPORT': { 

865 'Export_Id': 101, 

866 'CLIENT': {'Clients': 'ip1', 'Access_Level': 'ro'}, 

867 } 

868 } 

869 self.mock_object(self._manager, '_read_export', 

870 mock.Mock(return_value=test_dict_unicode)) 

871 self.mock_object(self._manager, '_write_export', 

872 mock.Mock(return_value=test_path)) 

873 self.mock_object(self._manager, '_dbus_send_ganesha') 

874 self.mock_object(self._manager, '_rm_file') 

875 

876 self._manager.update_export(test_name, confdict) 

877 

878 self._manager._read_export.assert_called_once_with(test_name) 

879 self._manager._write_export.assert_called_once_with(test_name, 

880 confdict) 

881 self._manager._dbus_send_ganesha.assert_called_once_with( 

882 'UpdateExport', 'string:' + test_path, 

883 'string:EXPORT(Export_Id=101)') 

884 if rados_store_enable: 

885 self._manager._rm_file.assert_called_once_with(test_path) 

886 else: 

887 self.assertFalse(self._manager._rm_file.called) 

888 

889 @ddt.data(True, False) 

890 def test_update_export_error_with_rados_store(self, rados_store_enable): 

891 self._manager.ganesha_rados_store_enable = rados_store_enable 

892 confdict = { 

893 'EXPORT': { 

894 'Export_Id': 101, 

895 'CLIENT': {'Clients': 'ip1', 'Access_Level': 'ro'}, 

896 } 

897 } 

898 self.mock_object(self._manager, '_read_export', 

899 mock.Mock(return_value=test_dict_unicode)) 

900 self.mock_object(self._manager, '_write_export', 

901 mock.Mock(return_value=test_path)) 

902 self.mock_object( 

903 self._manager, '_dbus_send_ganesha', 

904 mock.Mock(side_effect=exception.GaneshaCommandFailure)) 

905 self.mock_object(self._manager, '_rm_file') 

906 

907 self.assertRaises(exception.GaneshaCommandFailure, 

908 self._manager.update_export, test_name, confdict) 

909 

910 self._manager._read_export.assert_called_once_with(test_name) 

911 self._manager._write_export.assert_has_calls([ 

912 mock.call(test_name, confdict), 

913 mock.call(test_name, test_dict_unicode)]) 

914 self._manager._dbus_send_ganesha.assert_called_once_with( 

915 'UpdateExport', 'string:' + test_path, 

916 'string:EXPORT(Export_Id=101)') 

917 if rados_store_enable: 

918 self._manager._rm_file.assert_called_once_with(test_path) 

919 else: 

920 self.assertFalse(self._manager._rm_file.called) 

921 

922 @ddt.data(True, False) 

923 def test_remove_export_with_rados_store(self, rados_store_enable): 

924 self._manager.ganesha_rados_store_enable = rados_store_enable 

925 self.mock_object(self._manager, '_read_export', 

926 mock.Mock(return_value=test_dict_unicode)) 

927 self.mock_object(self._manager, '_get_export_rados_object_name', 

928 mock.Mock(return_value='fakeobj')) 

929 methods = ('_remove_export_dbus', '_rm_export_file', '_mkindex', 

930 '_remove_rados_object_url_from_index', 

931 '_delete_rados_object') 

932 for method in methods: 

933 self.mock_object(self._manager, method) 

934 

935 ret = self._manager.remove_export(test_name) 

936 

937 self._manager._read_export.assert_called_once_with(test_name) 

938 self._manager._remove_export_dbus.assert_called_once_with( 

939 test_dict_unicode['EXPORT']['Export_Id']) 

940 if rados_store_enable: 

941 (self._manager._get_export_rados_object_name. 

942 assert_called_once_with(test_name)) 

943 self._manager._delete_rados_object.assert_called_once_with( 

944 'fakeobj') 

945 (self._manager._remove_rados_object_url_from_index. 

946 assert_called_once_with(test_name)) 

947 self.assertFalse(self._manager._rm_export_file.called) 

948 self.assertFalse(self._manager._mkindex.called) 

949 else: 

950 self._manager._rm_export_file.assert_called_once_with(test_name) 

951 self._manager._mkindex.assert_called_once_with() 

952 self.assertFalse( 

953 self._manager._get_export_rados_object_name.called) 

954 self.assertFalse(self._manager._delete_rados_object.called) 

955 self.assertFalse( 

956 self._manager._remove_rados_object_url_from_index.called) 

957 self.assertIsNone(ret) 

958 

959 @ddt.data(True, False) 

960 def test_remove_export_error_during_read_export_with_rados_store( 

961 self, rados_store_enable): 

962 self._manager.ganesha_rados_store_enable = rados_store_enable 

963 self.mock_object( 

964 self._manager, '_read_export', 

965 mock.Mock(side_effect=exception.GaneshaCommandFailure)) 

966 self.mock_object(self._manager, '_get_export_rados_object_name', 

967 mock.Mock(return_value='fakeobj')) 

968 methods = ('_remove_export_dbus', '_rm_export_file', '_mkindex', 

969 '_remove_rados_object_url_from_index', 

970 '_delete_rados_object') 

971 for method in methods: 

972 self.mock_object(self._manager, method) 

973 

974 ret = self._manager.remove_export(test_name) 

975 

976 self._manager._read_export.assert_called_once_with(test_name) 

977 self.assertFalse(self._manager._remove_export_dbus.called) 

978 if rados_store_enable: 

979 (self._manager._get_export_rados_object_name. 

980 assert_called_once_with(test_name)) 

981 self._manager._delete_rados_object.assert_called_once_with( 

982 'fakeobj') 

983 (self._manager._remove_rados_object_url_from_index. 

984 assert_called_once_with(test_name)) 

985 self.assertFalse(self._manager._rm_export_file.called) 

986 self.assertFalse(self._manager._mkindex.called) 

987 else: 

988 self._manager._rm_export_file.assert_called_once_with(test_name) 

989 self._manager._mkindex.assert_called_once_with() 

990 self.assertFalse( 

991 self._manager._get_export_rados_object_name.called) 

992 self.assertFalse(self._manager._delete_rados_object.called) 

993 self.assertFalse( 

994 self._manager._remove_rados_object_url_from_index.called) 

995 self.assertIsNone(ret) 

996 

997 @ddt.data(True, False) 

998 def test_remove_export_error_during_remove_export_dbus_with_rados_store( 

999 self, rados_store_enable): 

1000 self._manager.ganesha_rados_store_enable = rados_store_enable 

1001 self.mock_object(self._manager, '_read_export', 

1002 mock.Mock(return_value=test_dict_unicode)) 

1003 self.mock_object(self._manager, '_get_export_rados_object_name', 

1004 mock.Mock(return_value='fakeobj')) 

1005 self.mock_object( 

1006 self._manager, '_remove_export_dbus', 

1007 mock.Mock(side_effect=exception.GaneshaCommandFailure)) 

1008 methods = ('_rm_export_file', '_mkindex', 

1009 '_remove_rados_object_url_from_index', 

1010 '_delete_rados_object') 

1011 for method in methods: 

1012 self.mock_object(self._manager, method) 

1013 

1014 ret = self._manager.remove_export(test_name) 

1015 

1016 self._manager._read_export.assert_called_once_with(test_name) 

1017 self._manager._remove_export_dbus.assert_called_once_with( 

1018 test_dict_unicode['EXPORT']['Export_Id']) 

1019 if rados_store_enable: 

1020 (self._manager._get_export_rados_object_name. 

1021 assert_called_once_with(test_name)) 

1022 self._manager._delete_rados_object.assert_called_once_with( 

1023 'fakeobj') 

1024 (self._manager._remove_rados_object_url_from_index. 

1025 assert_called_once_with(test_name)) 

1026 self.assertFalse(self._manager._rm_export_file.called) 

1027 self.assertFalse(self._manager._mkindex.called) 

1028 else: 

1029 self._manager._rm_export_file.assert_called_once_with(test_name) 

1030 self._manager._mkindex.assert_called_once_with() 

1031 self.assertFalse( 

1032 self._manager._get_export_rados_object_name.called) 

1033 self.assertFalse(self._manager._delete_rados_object.called) 

1034 self.assertFalse( 

1035 self._manager._remove_rados_object_url_from_index.called) 

1036 self.assertIsNone(ret) 

1037 

1038 def test_get_rados_object(self): 

1039 fakebin = chr(246).encode('utf-8') 

1040 

1041 ioctx = mock.Mock() 

1042 ioctx.read.side_effect = [fakebin, fakebin] 

1043 

1044 self._rados_client.open_ioctx = mock.Mock(return_value=ioctx) 

1045 self._rados_client.conf_get = mock.Mock(return_value=256) 

1046 

1047 max_size = 256 * 1024 * 1024 

1048 

1049 ret = self._manager_with_rados_store._get_rados_object('fakeobj') 

1050 

1051 self._rados_client.open_ioctx.assert_called_once_with('fakepool') 

1052 self._rados_client.conf_get.assert_called_once_with( 

1053 'osd_max_write_size') 

1054 ioctx.read.assert_called_once_with('fakeobj', max_size) 

1055 ioctx.close.assert_called_once() 

1056 

1057 self.assertEqual(fakebin.decode('utf-8'), ret) 

1058 

1059 def test_put_rados_object(self): 

1060 faketext = chr(246) 

1061 

1062 ioctx = mock.Mock() 

1063 manager.rados.WriteOpCtx.write_full = mock.Mock() 

1064 

1065 self._rados_client.open_ioctx = mock.Mock(return_value=ioctx) 

1066 self._rados_client.conf_get = mock.Mock(return_value=256) 

1067 

1068 ret = self._manager_with_rados_store._put_rados_object( 

1069 'fakeobj', faketext) 

1070 

1071 self._rados_client.open_ioctx.assert_called_once_with('fakepool') 

1072 self._rados_client.conf_get.assert_called_once_with( 

1073 'osd_max_write_size') 

1074 manager.rados.WriteOpCtx.write_full.assert_called_once_with( 

1075 faketext.encode('utf-8')) 

1076 ioctx.operate_write_op.assert_called_once_with(mock.ANY, 'fakeobj') 

1077 

1078 self.assertIsNone(ret) 

1079 

1080 def test_delete_rados_object(self): 

1081 ioctx = mock.Mock() 

1082 

1083 self._rados_client.open_ioctx = mock.Mock(return_value=ioctx) 

1084 

1085 ret = self._manager_with_rados_store._delete_rados_object('fakeobj') 

1086 

1087 self._rados_client.open_ioctx.assert_called_once_with('fakepool') 

1088 ioctx.remove_object.assert_called_once_with('fakeobj') 

1089 ioctx.close.assert_called_once() 

1090 

1091 self.assertIsNone(ret) 

1092 

1093 def test_get_export_id(self): 

1094 self.mock_object(self._manager, 'execute', 

1095 mock.Mock(return_value=('exportid|101', ''))) 

1096 ret = self._manager.get_export_id() 

1097 self._manager.execute.assert_called_once_with( 

1098 'sqlite3', self._manager.ganesha_db_path, 

1099 'update ganesha set value = value + 1;' 

1100 'select * from ganesha where key = "exportid";', 

1101 run_as_root=False) 

1102 self.assertEqual(101, ret) 

1103 

1104 def test_get_export_id_nobump(self): 

1105 self.mock_object(self._manager, 'execute', 

1106 mock.Mock(return_value=('exportid|101', ''))) 

1107 ret = self._manager.get_export_id(bump=False) 

1108 self._manager.execute.assert_called_once_with( 

1109 'sqlite3', self._manager.ganesha_db_path, 

1110 'select * from ganesha where key = "exportid";', 

1111 run_as_root=False) 

1112 self.assertEqual(101, ret) 

1113 

1114 def test_get_export_id_error_invalid_export_db(self): 

1115 self.mock_object(self._manager, 'execute', 

1116 mock.Mock(return_value=('invalid', ''))) 

1117 self.mock_object(manager.LOG, 'error') 

1118 self.assertRaises(exception.InvalidSqliteDB, 

1119 self._manager.get_export_id) 

1120 manager.LOG.error.assert_called_once_with( 

1121 mock.ANY, mock.ANY) 

1122 self._manager.execute.assert_called_once_with( 

1123 'sqlite3', self._manager.ganesha_db_path, 

1124 'update ganesha set value = value + 1;' 

1125 'select * from ganesha where key = "exportid";', 

1126 run_as_root=False) 

1127 

1128 @ddt.data(True, False) 

1129 def test_get_export_id_with_rados_store_and_bump(self, bump): 

1130 self.mock_object(self._manager_with_rados_store, 

1131 '_get_rados_object', mock.Mock(return_value='1000')) 

1132 self.mock_object(self._manager_with_rados_store, '_put_rados_object') 

1133 

1134 ret = self._manager_with_rados_store.get_export_id(bump=bump) 

1135 

1136 if bump: 

1137 (self._manager_with_rados_store._get_rados_object. 

1138 assert_called_once_with('fakecounter')) 

1139 (self._manager_with_rados_store._put_rados_object. 

1140 assert_called_once_with('fakecounter', '1001')) 

1141 self.assertEqual(1001, ret) 

1142 else: 

1143 (self._manager_with_rados_store._get_rados_object. 

1144 assert_called_once_with('fakecounter')) 

1145 self.assertFalse( 

1146 self._manager_with_rados_store._put_rados_object.called) 

1147 self.assertEqual(1000, ret) 

1148 

1149 def test_restart_service(self): 

1150 self.mock_object(self._manager, 'execute') 

1151 ret = self._manager.restart_service() 

1152 self._manager.execute.assert_called_once_with( 

1153 'service', 'ganesha.fakeservice', 'restart') 

1154 self.assertIsNone(ret) 

1155 

1156 def test_reset_exports(self): 

1157 self.mock_object(self._manager, 'execute') 

1158 self.mock_object(self._manager, '_mkindex') 

1159 ret = self._manager.reset_exports() 

1160 self._manager.execute.assert_called_once_with( 

1161 'sh', '-c', 'rm -f /fakedir0/export.d/*.conf') 

1162 self._manager._mkindex.assert_called_once_with() 

1163 self.assertIsNone(ret)