Coverage for manila/tests/share/drivers/test_ganesha.py: 100%
314 statements
« prev ^ index » next coverage.py v7.11.0, created at 2026-02-18 22:19 +0000
« prev ^ index » next coverage.py v7.11.0, created at 2026-02-18 22:19 +0000
1# Copyright (c) 2014 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.
16import copy
17import errno
18import os
19from unittest import mock
21import ddt
22from oslo_config import cfg
24from manila import context
25from manila import exception
26from manila.share import configuration as config
27from manila.share.drivers import ganesha
28from manila import test
29from manila.tests import fake_share
31CONF = cfg.CONF
34fake_basepath = '/fakepath'
36fake_export_name = 'fakename--fakeaccid'
38fake_output_template = {
39 'EXPORT': {
40 'Export_Id': 101,
41 'Path': '/fakepath/fakename',
42 'Pseudo': '/fakepath/fakename--fakeaccid',
43 'Tag': 'fakeaccid',
44 'CLIENT': {
45 'Clients': '10.0.0.1'
46 },
47 'FSAL': 'fakefsal'
48 }
49}
52@ddt.ddt
53class GaneshaNASHelperTestCase(test.TestCase):
54 """Tests GaneshaNASHElper."""
56 def setUp(self):
57 super(GaneshaNASHelperTestCase, self).setUp()
59 CONF.set_default('ganesha_config_path', '/fakedir0/fakeconfig')
60 CONF.set_default('ganesha_db_path', '/fakedir1/fake.db')
61 CONF.set_default('ganesha_export_dir', '/fakedir0/export.d')
62 CONF.set_default('ganesha_export_template_dir',
63 '/fakedir2/faketempl.d')
64 CONF.set_default('ganesha_service_name', 'ganesha.fakeservice')
65 self._context = context.get_admin_context()
66 self._execute = mock.Mock(return_value=('', ''))
67 self.fake_conf = config.Configuration(None)
68 self.fake_conf_dir_path = '/fakedir0/exports.d'
69 self._helper = ganesha.GaneshaNASHelper(
70 self._execute, self.fake_conf, tag='faketag')
71 self._helper.ganesha = mock.Mock()
72 self._helper.export_template = {'key': 'value'}
73 self.share = fake_share.fake_share()
74 self.access = fake_share.fake_access()
76 def test_load_conf_dir(self):
77 fake_template1 = {'key': 'value1'}
78 fake_template2 = {'key': 'value2'}
79 fake_ls_dir = ['fakefile0.conf', 'fakefile1.json', 'fakefile2.txt']
80 mock_ganesha_utils_patch = mock.Mock()
82 def fake_patch_run(tmpl1, tmpl2):
83 mock_ganesha_utils_patch(
84 copy.deepcopy(tmpl1), copy.deepcopy(tmpl2))
85 tmpl1.update(tmpl2)
87 self.mock_object(ganesha.os, 'listdir',
88 mock.Mock(return_value=fake_ls_dir))
89 self.mock_object(ganesha.LOG, 'info')
90 self.mock_object(ganesha.ganesha_manager, 'parseconf',
91 mock.Mock(side_effect=[fake_template1,
92 fake_template2]))
93 self.mock_object(ganesha.ganesha_utils, 'patch',
94 mock.Mock(side_effect=fake_patch_run))
95 with mock.patch('builtins.open',
96 mock.mock_open()) as mockopen:
97 mockopen().read.side_effect = ['fakeconf0', 'fakeconf1']
98 ret = self._helper._load_conf_dir(self.fake_conf_dir_path)
99 ganesha.os.listdir.assert_called_once_with(
100 self.fake_conf_dir_path)
101 ganesha.LOG.info.assert_called_once_with(
102 mock.ANY, self.fake_conf_dir_path)
103 mockopen.assert_has_calls([
104 mock.call('/fakedir0/exports.d/fakefile0.conf'),
105 mock.call('/fakedir0/exports.d/fakefile1.json')],
106 any_order=True)
107 ganesha.ganesha_manager.parseconf.assert_has_calls([
108 mock.call('fakeconf0'), mock.call('fakeconf1')])
109 mock_ganesha_utils_patch.assert_has_calls([
110 mock.call({}, fake_template1),
111 mock.call(fake_template1, fake_template2)])
112 self.assertEqual(fake_template2, ret)
114 def test_load_conf_dir_no_conf_dir_must_exist_false(self):
115 self.mock_object(
116 ganesha.os, 'listdir',
117 mock.Mock(side_effect=OSError(errno.ENOENT,
118 os.strerror(errno.ENOENT))))
119 self.mock_object(ganesha.LOG, 'info')
120 self.mock_object(ganesha.ganesha_manager, 'parseconf')
121 self.mock_object(ganesha.ganesha_utils, 'patch')
122 with mock.patch('builtins.open',
123 mock.mock_open(read_data='fakeconf')) as mockopen:
124 ret = self._helper._load_conf_dir(self.fake_conf_dir_path,
125 must_exist=False)
126 ganesha.os.listdir.assert_called_once_with(
127 self.fake_conf_dir_path)
128 ganesha.LOG.info.assert_called_once_with(
129 mock.ANY, self.fake_conf_dir_path)
130 self.assertFalse(mockopen.called)
131 self.assertFalse(ganesha.ganesha_manager.parseconf.called)
132 self.assertFalse(ganesha.ganesha_utils.patch.called)
133 self.assertEqual({}, ret)
135 def test_load_conf_dir_error_no_conf_dir_must_exist_true(self):
136 self.mock_object(
137 ganesha.os, 'listdir',
138 mock.Mock(side_effect=OSError(errno.ENOENT,
139 os.strerror(errno.ENOENT))))
140 self.assertRaises(OSError, self._helper._load_conf_dir,
141 self.fake_conf_dir_path)
142 ganesha.os.listdir.assert_called_once_with(self.fake_conf_dir_path)
144 def test_load_conf_dir_error_conf_dir_present_must_exist_false(self):
145 self.mock_object(
146 ganesha.os, 'listdir',
147 mock.Mock(side_effect=OSError(errno.EACCES,
148 os.strerror(errno.EACCES))))
149 self.assertRaises(OSError, self._helper._load_conf_dir,
150 self.fake_conf_dir_path, must_exist=False)
151 ganesha.os.listdir.assert_called_once_with(self.fake_conf_dir_path)
153 def test_load_conf_dir_error(self):
154 self.mock_object(
155 ganesha.os, 'listdir',
156 mock.Mock(side_effect=RuntimeError('fake error')))
157 self.assertRaises(RuntimeError, self._helper._load_conf_dir,
158 self.fake_conf_dir_path)
159 ganesha.os.listdir.assert_called_once_with(self.fake_conf_dir_path)
161 def test_init_helper(self):
162 mock_template = mock.Mock()
163 mock_ganesha_manager = mock.Mock()
164 self.mock_object(ganesha.ganesha_manager, 'GaneshaManager',
165 mock.Mock(return_value=mock_ganesha_manager))
166 self.mock_object(self._helper, '_load_conf_dir',
167 mock.Mock(return_value=mock_template))
168 self.mock_object(self._helper, '_default_config_hook')
169 ret = self._helper.init_helper()
170 ganesha.ganesha_manager.GaneshaManager.assert_called_once_with(
171 self._execute, 'faketag',
172 ganesha_config_path='/fakedir0/fakeconfig',
173 ganesha_export_dir='/fakedir0/export.d',
174 ganesha_db_path='/fakedir1/fake.db',
175 ganesha_service_name='ganesha.fakeservice')
176 self._helper._load_conf_dir.assert_called_once_with(
177 '/fakedir2/faketempl.d', must_exist=False)
178 self.assertFalse(self._helper._default_config_hook.called)
179 self.assertEqual(mock_ganesha_manager, self._helper.ganesha)
180 self.assertEqual(mock_template, self._helper.export_template)
181 self.assertIsNone(ret)
183 def test_init_helper_conf_dir_empty(self):
184 mock_template = mock.Mock()
185 mock_ganesha_manager = mock.Mock()
186 self.mock_object(ganesha.ganesha_manager, 'GaneshaManager',
187 mock.Mock(return_value=mock_ganesha_manager))
188 self.mock_object(self._helper, '_load_conf_dir',
189 mock.Mock(return_value={}))
190 self.mock_object(self._helper, '_default_config_hook',
191 mock.Mock(return_value=mock_template))
192 ret = self._helper.init_helper()
193 ganesha.ganesha_manager.GaneshaManager.assert_called_once_with(
194 self._execute, 'faketag',
195 ganesha_config_path='/fakedir0/fakeconfig',
196 ganesha_export_dir='/fakedir0/export.d',
197 ganesha_db_path='/fakedir1/fake.db',
198 ganesha_service_name='ganesha.fakeservice')
199 self._helper._load_conf_dir.assert_called_once_with(
200 '/fakedir2/faketempl.d', must_exist=False)
201 self._helper._default_config_hook.assert_called_once_with()
202 self.assertEqual(mock_ganesha_manager, self._helper.ganesha)
203 self.assertEqual(mock_template, self._helper.export_template)
204 self.assertIsNone(ret)
206 def test_default_config_hook(self):
207 fake_template = {'key': 'value'}
208 self.mock_object(ganesha.ganesha_utils, 'path_from',
209 mock.Mock(return_value='/fakedir3/fakeconfdir'))
210 self.mock_object(self._helper, '_load_conf_dir',
211 mock.Mock(return_value=fake_template))
212 ret = self._helper._default_config_hook()
213 ganesha.ganesha_utils.path_from.assert_called_once_with(
214 ganesha.__file__, 'conf')
215 self._helper._load_conf_dir.assert_called_once_with(
216 '/fakedir3/fakeconfdir')
217 self.assertEqual(fake_template, ret)
219 def test_fsal_hook(self):
220 ret = self._helper._fsal_hook('/fakepath', self.share, self.access)
221 self.assertEqual({}, ret)
223 def test_cleanup_fsal_hook(self):
224 ret = self._helper._cleanup_fsal_hook('/fakepath', self.share,
225 self.access)
226 self.assertIsNone(ret)
228 def test_allow_access(self):
229 mock_ganesha_utils_patch = mock.Mock()
231 def fake_patch_run(tmpl1, tmpl2, tmpl3):
232 mock_ganesha_utils_patch(copy.deepcopy(tmpl1), tmpl2, tmpl3)
233 tmpl1.update(tmpl3)
235 self.mock_object(self._helper.ganesha, 'get_export_id',
236 mock.Mock(return_value=101))
237 self.mock_object(self._helper, '_fsal_hook',
238 mock.Mock(return_value='fakefsal'))
239 self.mock_object(ganesha.ganesha_utils, 'patch',
240 mock.Mock(side_effect=fake_patch_run))
241 self.mock_object(ganesha.ganesha_utils, 'validate_access_rule',
242 mock.Mock(return_value=True))
243 ret = self._helper._allow_access(fake_basepath, self.share,
244 self.access)
245 self._helper.ganesha.get_export_id.assert_called_once_with()
246 self._helper._fsal_hook.assert_called_once_with(
247 fake_basepath, self.share, self.access, sub_name=None)
248 mock_ganesha_utils_patch.assert_called_once_with(
249 {}, self._helper.export_template, fake_output_template)
250 self._helper._fsal_hook.assert_called_once_with(
251 fake_basepath, self.share, self.access, sub_name=None)
252 self._helper.ganesha.add_export.assert_called_once_with(
253 fake_export_name, fake_output_template)
254 self.assertIsNone(ret)
256 def test_allow_access_error_invalid_share(self):
257 access = fake_share.fake_access(access_type='notip')
258 self.assertRaises(exception.InvalidShareAccess,
259 self._helper._allow_access, '/fakepath',
260 self.share, access)
262 def test_deny_access(self):
263 ret = self._helper._deny_access('/fakepath', self.share, self.access)
264 self._helper.ganesha.remove_export.assert_called_once_with(
265 'fakename--fakeaccid')
266 self.assertIsNone(ret)
268 def test_update_access_for_allow(self):
269 self.mock_object(self._helper, '_allow_access')
270 self.mock_object(self._helper, '_deny_access')
272 self._helper.update_access(
273 self._context, self.share, access_rules=[self.access],
274 add_rules=[self.access], delete_rules=[], update_rules=[])
276 self._helper._allow_access.assert_called_once_with(
277 '/', self.share, self.access)
279 self.assertFalse(self._helper._deny_access.called)
280 self.assertFalse(self._helper.ganesha.reset_exports.called)
281 self.assertFalse(self._helper.ganesha.restart_service.called)
283 def test_update_access_for_deny(self):
284 self.mock_object(self._helper, '_allow_access')
285 self.mock_object(self._helper, '_deny_access')
287 self._helper.update_access(
288 self._context, self.share, access_rules=[],
289 add_rules=[], delete_rules=[self.access], update_rules=[])
291 self._helper._deny_access.assert_called_once_with(
292 '/', self.share, self.access)
294 self.assertFalse(self._helper._allow_access.called)
295 self.assertFalse(self._helper.ganesha.reset_exports.called)
296 self.assertFalse(self._helper.ganesha.restart_service.called)
298 def test_update_access_recovery(self):
299 self.mock_object(self._helper, '_allow_access')
300 self.mock_object(self._helper, '_deny_access')
302 self._helper.update_access(
303 self._context, self.share, access_rules=[self.access],
304 add_rules=[], delete_rules=[], update_rules=[])
306 self._helper._allow_access.assert_called_once_with(
307 '/', self.share, self.access)
309 self.assertFalse(self._helper._deny_access.called)
310 self.assertTrue(self._helper.ganesha.reset_exports.called)
311 self.assertTrue(self._helper.ganesha.restart_service.called)
313 def test_update_access_invalid_share_access_type(self):
314 bad_rule = fake_share.fake_access(access_type='notip', id='fakeid')
315 expected = {'fakeid': {'state': 'error'}}
317 result = self._helper.update_access(self._context, self.share,
318 access_rules=[bad_rule],
319 add_rules=[], delete_rules=[],
320 update_rules=[])
322 self.assertEqual(expected, result)
324 def test_update_access_invalid_share_access_level(self):
325 bad_rule = fake_share.fake_access(access_level='RO', id='fakeid')
326 expected = {'fakeid': {'state': 'error'}}
328 result = self._helper.update_access(self._context, self.share,
329 access_rules=[bad_rule],
330 add_rules=[], delete_rules=[],
331 update_rules=[])
333 self.assertEqual(expected, result)
336@ddt.ddt
337class GaneshaNASHelper2TestCase(test.TestCase):
338 """Tests GaneshaNASHelper2."""
340 def setUp(self):
341 super(GaneshaNASHelper2TestCase, self).setUp()
343 CONF.set_default('ganesha_config_path', '/fakedir0/fakeconfig')
344 CONF.set_default('ganesha_db_path', '/fakedir1/fake.db')
345 CONF.set_default('ganesha_export_dir', '/fakedir0/export.d')
346 CONF.set_default('ganesha_export_template_dir',
347 '/fakedir2/faketempl.d')
348 CONF.set_default('ganesha_service_name', 'ganesha.fakeservice')
349 CONF.set_default('ganesha_rados_store_enable', True)
350 CONF.set_default('ganesha_rados_store_pool_name', 'ceph_pool')
351 CONF.set_default('ganesha_rados_export_index', 'fake_index')
352 CONF.set_default('ganesha_rados_export_counter', 'fake_counter')
354 self._context = context.get_admin_context()
355 self._execute = mock.Mock(return_value=('', ''))
356 self.rados_client = mock.Mock()
357 self.fake_conf = config.Configuration(None)
358 self.fake_conf_dir_path = '/fakedir0/exports.d'
359 self._helper = ganesha.GaneshaNASHelper2(
360 self._execute, self.fake_conf, tag='faketag',
361 rados_client=self.rados_client)
362 self._helper.ganesha = mock.Mock()
363 self._helper.export_template = {}
364 self.share = fake_share.fake_share()
365 self.rule1 = fake_share.fake_access(access_level='ro')
366 self.rule2 = fake_share.fake_access(access_level='rw',
367 access_to='10.0.0.2')
369 @ddt.data(False, True)
370 def test_init_helper_with_rados_store(self, rados_store_enable):
371 CONF.set_default('ganesha_rados_store_enable', rados_store_enable)
372 mock_template = mock.Mock()
373 mock_ganesha_manager = mock.Mock()
374 self.mock_object(ganesha.ganesha_manager, 'GaneshaManager',
375 mock.Mock(return_value=mock_ganesha_manager))
376 self.mock_object(self._helper, '_load_conf_dir',
377 mock.Mock(return_value={}))
378 self.mock_object(self._helper, '_default_config_hook',
379 mock.Mock(return_value=mock_template))
381 ret = self._helper.init_helper()
383 if rados_store_enable:
384 kwargs = {
385 'ganesha_config_path': '/fakedir0/fakeconfig',
386 'ganesha_export_dir': '/fakedir0/export.d',
387 'ganesha_service_name': 'ganesha.fakeservice',
388 'ganesha_rados_store_enable': True,
389 'ganesha_rados_store_pool_name': 'ceph_pool',
390 'ganesha_rados_export_index': 'fake_index',
391 'ganesha_rados_export_counter': 'fake_counter',
392 'rados_client': self.rados_client
393 }
394 else:
395 kwargs = {
396 'ganesha_config_path': '/fakedir0/fakeconfig',
397 'ganesha_export_dir': '/fakedir0/export.d',
398 'ganesha_service_name': 'ganesha.fakeservice',
399 'ganesha_db_path': '/fakedir1/fake.db'
400 }
401 ganesha.ganesha_manager.GaneshaManager.assert_called_once_with(
402 self._execute, '<no name>', **kwargs)
403 self._helper._load_conf_dir.assert_called_once_with(
404 '/fakedir2/faketempl.d', must_exist=False)
405 self.assertEqual(mock_ganesha_manager, self._helper.ganesha)
406 self._helper._default_config_hook.assert_called_once_with()
407 self.assertEqual(mock_template, self._helper.export_template)
408 self.assertIsNone(ret)
410 @ddt.data(False, True)
411 def test_init_helper_conf_dir_empty(self, conf_dir_empty):
412 mock_template = mock.Mock()
413 mock_ganesha_manager = mock.Mock()
414 self.mock_object(ganesha.ganesha_manager, 'GaneshaManager',
415 mock.Mock(return_value=mock_ganesha_manager))
416 if conf_dir_empty:
417 self.mock_object(self._helper, '_load_conf_dir',
418 mock.Mock(return_value={}))
419 else:
420 self.mock_object(self._helper, '_load_conf_dir',
421 mock.Mock(return_value=mock_template))
422 self.mock_object(self._helper, '_default_config_hook',
423 mock.Mock(return_value=mock_template))
425 ret = self._helper.init_helper()
427 ganesha.ganesha_manager.GaneshaManager.assert_called_once_with(
428 self._execute, '<no name>',
429 ganesha_config_path='/fakedir0/fakeconfig',
430 ganesha_export_dir='/fakedir0/export.d',
431 ganesha_service_name='ganesha.fakeservice',
432 ganesha_rados_store_enable=True,
433 ganesha_rados_store_pool_name='ceph_pool',
434 ganesha_rados_export_index='fake_index',
435 ganesha_rados_export_counter='fake_counter',
436 rados_client=self.rados_client)
437 self._helper._load_conf_dir.assert_called_once_with(
438 '/fakedir2/faketempl.d', must_exist=False)
439 self.assertEqual(mock_ganesha_manager, self._helper.ganesha)
440 if conf_dir_empty:
441 self._helper._default_config_hook.assert_called_once_with()
442 else:
443 self.assertFalse(self._helper._default_config_hook.called)
444 self.assertEqual(mock_template, self._helper.export_template)
445 self.assertIsNone(ret)
447 def test_init_helper_with_rados_store_pool_name_not_set(self):
448 self.mock_object(ganesha.ganesha_manager, 'GaneshaManager')
449 self.mock_object(self._helper, '_load_conf_dir')
450 self.mock_object(self._helper, '_default_config_hook')
451 self._helper.configuration.ganesha_rados_store_pool_name = None
453 self.assertRaises(
454 exception.GaneshaException, self._helper.init_helper)
456 self.assertFalse(ganesha.ganesha_manager.GaneshaManager.called)
457 self.assertFalse(self._helper._load_conf_dir.called)
458 self.assertFalse(self._helper._default_config_hook.called)
460 def test_update_access_add_export(self):
461 mock_gh = self._helper.ganesha
462 self.mock_object(mock_gh, 'check_export_exists',
463 mock.Mock(return_value=False))
464 self.mock_object(mock_gh, 'get_export_id',
465 mock.Mock(return_value=100))
466 self.mock_object(self._helper, '_get_export_path',
467 mock.Mock(return_value='/fakepath'))
468 self.mock_object(self._helper, '_get_export_pseudo_path',
469 mock.Mock(return_value='/fakepath'))
470 self.mock_object(self._helper, '_fsal_hook',
471 mock.Mock(return_value={'Name': 'fake'}))
472 self.mock_object(ganesha.ganesha_utils, 'validate_access_rule',
473 mock.Mock(return_value=True))
474 result_confdict = {
475 'EXPORT': {
476 'Export_Id': 100,
477 'Path': '/fakepath',
478 'Pseudo': '/fakepath',
479 'Tag': 'fakename',
480 'CLIENT': [{
481 'Access_Type': 'ro',
482 'Clients': '10.0.0.1'}],
483 'FSAL': {'Name': 'fake'}
484 }
485 }
487 self._helper.update_access(
488 self._context, self.share, access_rules=[self.rule1],
489 add_rules=[], delete_rules=[], update_rules=[])
491 mock_gh.check_export_exists.assert_called_once_with('fakename')
492 mock_gh.get_export_id.assert_called_once_with()
493 self._helper._get_export_path.assert_called_once_with(
494 self.share, sub_name=None)
495 (self._helper._get_export_pseudo_path.assert_called_once_with(
496 self.share, sub_name=None))
497 self._helper._fsal_hook.assert_called_once_with(
498 None, self.share, None, sub_name=None)
499 mock_gh.add_export.assert_called_once_with(
500 'fakename', result_confdict)
501 self.assertFalse(mock_gh.update_export.called)
502 self.assertFalse(mock_gh.remove_export.called)
504 @ddt.data({'Access_Type': 'ro', 'Clients': '10.0.0.1'},
505 [{'Access_Type': 'ro', 'Clients': '10.0.0.1'}])
506 def test_update_access_update_export(self, client):
507 mock_gh = self._helper.ganesha
508 self.mock_object(mock_gh, 'check_export_exists',
509 mock.Mock(return_value=True))
510 self.mock_object(
511 mock_gh, '_read_export',
512 mock.Mock(return_value={'EXPORT': {'CLIENT': client}})
513 )
514 self.mock_object(ganesha.ganesha_utils, 'validate_access_rule',
515 mock.Mock(return_value=True))
516 result_confdict = {
517 'EXPORT': {
518 'CLIENT': [
519 {'Access_Type': 'ro', 'Clients': '10.0.0.1'},
520 {'Access_Type': 'rw', 'Clients': '10.0.0.2'}]
521 }
522 }
524 self._helper.update_access(
525 self._context, self.share, access_rules=[self.rule1, self.rule2],
526 add_rules=[self.rule2], delete_rules=[], update_rules=[])
528 mock_gh.check_export_exists.assert_called_once_with('fakename')
529 mock_gh.update_export.assert_called_once_with('fakename',
530 result_confdict)
531 self.assertFalse(mock_gh.add_export.called)
532 self.assertFalse(mock_gh.remove_export.called)
534 def test_update_access_remove_export(self):
535 mock_gh = self._helper.ganesha
536 self.mock_object(mock_gh, 'check_export_exists',
537 mock.Mock(return_value=True))
538 self.mock_object(self._helper, '_cleanup_fsal_hook')
539 client = {'Access_Type': 'ro', 'Clients': '10.0.0.1'}
540 self.mock_object(
541 mock_gh, '_read_export',
542 mock.Mock(return_value={'EXPORT': {'CLIENT': client}})
543 )
545 self._helper.update_access(
546 self._context, self.share, access_rules=[],
547 add_rules=[], delete_rules=[self.rule1], update_rules=[])
549 mock_gh.check_export_exists.assert_called_once_with('fakename')
550 mock_gh.remove_export.assert_called_once_with('fakename')
551 self._helper._cleanup_fsal_hook.assert_called_once_with(
552 None, self.share, None, sub_name=None)
553 self.assertFalse(mock_gh.add_export.called)
554 self.assertFalse(mock_gh.update_export.called)
556 def test_update_access_export_file_already_removed(self):
557 mock_gh = self._helper.ganesha
558 self.mock_object(mock_gh, 'check_export_exists',
559 mock.Mock(return_value=False))
560 self.mock_object(ganesha.LOG, 'warning')
561 self.mock_object(self._helper, '_cleanup_fsal_hook')
563 self._helper.update_access(
564 self._context, self.share, access_rules=[],
565 add_rules=[], delete_rules=[self.rule1], update_rules=[])
567 mock_gh.check_export_exists.assert_called_once_with('fakename')
568 ganesha.LOG.warning.assert_called_once_with(mock.ANY, mock.ANY)
569 self.assertFalse(mock_gh.add_export.called)
570 self.assertFalse(mock_gh.update_export.called)
571 self.assertFalse(mock_gh.remove_export.called)
572 self.assertFalse(self._helper._cleanup_fsal_hook.called)
574 def test_update_access_invalid_share_access_type(self):
575 mock_gh = self._helper.ganesha
576 self.mock_object(mock_gh, 'check_export_exists',
577 mock.Mock(return_value=False))
578 bad_rule = fake_share.fake_access(access_type='notip', id='fakeid')
579 expected = {'fakeid': {'state': 'error'}}
581 result = self._helper.update_access(self._context, self.share,
582 access_rules=[bad_rule],
583 add_rules=[], delete_rules=[],
584 update_rules=[])
586 self.assertEqual(expected, result)
588 def test_update_access_invalid_share_access_level(self):
589 bad_rule = fake_share.fake_access(access_level='NOT_RO_OR_RW',
590 id='fakeid')
591 expected = {'fakeid': {'state': 'error'}}
592 mock_gh = self._helper.ganesha
593 self.mock_object(mock_gh, 'check_export_exists',
594 mock.Mock(return_value=False))
596 result = self._helper.update_access(self._context, self.share,
597 access_rules=[bad_rule],
598 add_rules=[], delete_rules=[],
599 update_rules=[])
601 self.assertEqual(expected, result)