Skip to content

Commit b8f3db5

Browse files
committed
mgr/nfs: add additional tests for cmount_path & user_id deletion
Add unit tests for unique user ID generation, deletion and `cmount_path` handling in FSAL exports - Ensure unique user ID generation for different FSAL blocks when creating exports. - Test deletion behavior when multiple exports share the same user ID and one has a unique ID. - Test default behavior when no `cmount_path` is provided (defaults to `/`). - Add tests to validate error handling for invalid `cmount_path` values. Signed-off-by: Avan Thakkar <athakkar@redhat.com>
1 parent d02b94d commit b8f3db5

File tree

2 files changed

+95
-7
lines changed

2 files changed

+95
-7
lines changed

qa/tasks/cephfs/test_nfs.py

Lines changed: 73 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
NFS_POOL_NAME = '.nfs' # should match mgr_module.py
1515

1616
# TODO Add test for cluster update when ganesha can be deployed on multiple ports.
17+
18+
1719
class TestNFS(MgrTestCase):
1820
def _cmd(self, *args):
1921
return self.get_ceph_cmd_stdout(args)
@@ -119,18 +121,20 @@ def _check_nfs_cluster_status(self, expected_status, fail_msg):
119121
return
120122
self.fail(fail_msg)
121123

122-
def _check_auth_ls(self, fs_name, check_in=False):
124+
def _check_auth_ls(self, fs_name, check_in=False, user_id=None):
123125
'''
124126
Tests export user id creation or deletion.
125127
:param export_id: Denotes export number
126128
:param check_in: Check specified export id
127129
'''
128130
output = self._cmd('auth', 'ls')
129131
client_id = f'client.nfs.{self.cluster_id}'
132+
search_id = f'client.{user_id}' if user_id else f'{client_id}.{fs_name}'
133+
130134
if check_in:
131-
self.assertIn(f'{client_id}.{fs_name}', output)
135+
self.assertIn(search_id, output)
132136
else:
133-
self.assertNotIn(f'{client_id}.{fs_name}', output)
137+
self.assertNotIn(search_id, output)
134138

135139
def _test_idempotency(self, cmd_func, cmd_args):
136140
'''
@@ -231,11 +235,11 @@ def _create_default_export(self):
231235
self._test_create_cluster()
232236
self._create_export(export_id='1', create_fs=True)
233237

234-
def _delete_export(self):
238+
def _delete_export(self, pseduo_path=None):
235239
'''
236240
Delete an export.
237241
'''
238-
self._nfs_cmd('export', 'rm', self.cluster_id, self.pseudo_path)
242+
self._nfs_cmd('export', 'rm', self.cluster_id, pseduo_path if pseduo_path else self.pseudo_path)
239243
self._check_auth_ls(self.fs_name)
240244

241245
def _test_list_export(self):
@@ -272,11 +276,12 @@ def _test_list_detailed(self, sub_vol_path):
272276
self.sample_export['fsal']['user_id'] = f'{self.expected_name}.{self.fs_name}.3746f603'
273277
self.assertDictEqual(self.sample_export, nfs_output[3])
274278

275-
def _get_export(self):
279+
def _get_export(self, pseudo_path=None):
276280
'''
277281
Returns export block in json format
278282
'''
279-
return json.loads(self._nfs_cmd('export', 'info', self.cluster_id, self.pseudo_path))
283+
return json.loads(self._nfs_cmd('export', 'info', self.cluster_id,
284+
pseudo_path if pseudo_path else self.pseudo_path))
280285

281286
def _test_get_export(self):
282287
'''
@@ -1212,3 +1217,64 @@ def test_cephfs_export_update_at_non_dir_path(self):
12121217
finally:
12131218
self.ctx.cluster.run(args=['rm', '-rf', f'{mnt_pt}/*'])
12141219
self._delete_cluster_with_fs(self.fs_name, mnt_pt, preserve_mode)
1220+
1221+
def test_nfs_export_creation_without_cmount_path(self):
1222+
"""
1223+
Test that ensure cmount_path is present in FSAL block
1224+
"""
1225+
pseudo_path = '/test_without_cmount'
1226+
self._create_export(export_id='1234',
1227+
extra_cmd=['--pseudo-path', pseudo_path])
1228+
nfs_output = self._get_export(pseudo_path)
1229+
self.assertIn('cmount_path', nfs_output['fsal'])
1230+
1231+
self._delete_export(pseudo_path)
1232+
1233+
def test_nfs_exports_with_same_and_diff_user_id(self):
1234+
"""
1235+
Test that exports with same FSAL share same user_id
1236+
"""
1237+
pseudo_path_1 = '/test1'
1238+
pseudo_path_2 = '/test2'
1239+
pseudo_path_3 = '/test3'
1240+
1241+
# Create subvolumes
1242+
self._cmd('fs', 'subvolume', 'create', self.fs_name, 'sub_vol_1')
1243+
self._cmd('fs', 'subvolume', 'create', self.fs_name, 'sub_vol_2')
1244+
1245+
fs_path_1 = self._cmd('fs', 'subvolume', 'getpath', self.fs_name, 'sub_vol_1').strip()
1246+
fs_path_2 = self._cmd('fs', 'subvolume', 'getpath', self.fs_name, 'sub_vol_2').strip()
1247+
# Both exports should have same user_id(since cmount_path=/ & fs_name is same)
1248+
self._create_export(export_id='21',
1249+
extra_cmd=['--pseudo-path', pseudo_path_1,
1250+
'--path', fs_path_1])
1251+
self._create_export(export_id='22',
1252+
extra_cmd=['--pseudo-path', pseudo_path_2,
1253+
'--path', fs_path_2])
1254+
1255+
nfs_output_1 = self._get_export(pseudo_path_1)
1256+
nfs_output_2 = self._get_export(pseudo_path_2)
1257+
# Check if both exports have same user_id
1258+
self.assertEqual(nfs_output_2['fsal']['user_id'], nfs_output_1['fsal']['user_id'])
1259+
self.assertEqual(nfs_output_1['fsal']['user_id'], 'nfs.test.nfs-cephfs.3746f603')
1260+
1261+
cmount_path = '/volumes'
1262+
self._create_export(export_id='23',
1263+
extra_cmd=['--pseudo-path', pseudo_path_3,
1264+
'--path', fs_path_1,
1265+
'--cmount-path', cmount_path])
1266+
1267+
nfs_output_3 = self._get_export(pseudo_path_3)
1268+
self.assertNotEqual(nfs_output_3['fsal']['user_id'], nfs_output_1['fsal']['user_id'])
1269+
self.assertEqual(nfs_output_3['fsal']['user_id'], 'nfs.test.nfs-cephfs.32cd8545')
1270+
1271+
self._delete_export(pseudo_path_1)
1272+
# Deleting export with same user_id should not delete the user_id
1273+
self._check_auth_ls(self.fs_name, True, nfs_output_2['fsal']['user_id'])
1274+
self._delete_export(pseudo_path_2)
1275+
# Deleting export 22 should delete the user_id since it's only export left with that user_id
1276+
self._check_auth_ls(self.fs_name, False, nfs_output_2['fsal']['user_id'])
1277+
1278+
self._delete_export(pseudo_path_3)
1279+
# Deleting export 23 should delete the user_id since it's only export with that user_id
1280+
self._check_auth_ls(self.fs_name, False, nfs_output_3['fsal']['user_id'])

src/pybind/mgr/nfs/tests/test_nfs.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1119,6 +1119,9 @@ def test_create_export_cephfs(self):
11191119

11201120
def test_create_export_cephfs_with_cmount_path(self):
11211121
self._do_mock_test(self._do_test_create_export_cephfs_with_cmount_path)
1122+
1123+
def test_create_export_cephfs_with_invalid_cmount_path(self):
1124+
self._do_mock_test(self._do_test_create_export_cephfs_with_invalid_cmount_path)
11221125

11231126
def _do_test_create_export_cephfs(self):
11241127
nfs_mod = Module('nfs', '', '')
@@ -1193,6 +1196,25 @@ def _do_test_create_export_cephfs_with_cmount_path(self):
11931196
assert export.fsal.cephx_key == "thekeyforclientabc"
11941197
assert export.fsal.cmount_path == "/"
11951198
assert export.cluster_id == self.cluster_id
1199+
1200+
def _do_test_create_export_cephfs_with_invalid_cmount_path(self):
1201+
import object_format
1202+
1203+
nfs_mod = Module('nfs', '', '')
1204+
conf = ExportMgr(nfs_mod)
1205+
1206+
with pytest.raises(object_format.ErrorResponse) as e:
1207+
conf.create_export(
1208+
fsal_type='cephfs',
1209+
cluster_id=self.cluster_id,
1210+
fs_name='myfs',
1211+
path='/',
1212+
pseudo_path='/cephfs4',
1213+
read_only=False,
1214+
squash='root',
1215+
cmount_path='/invalid',
1216+
)
1217+
assert "Invalid cmount_path: '/invalid'" in str(e.value)
11961218

11971219
def _do_test_cluster_ls(self):
11981220
nfs_mod = Module('nfs', '', '')

0 commit comments

Comments
 (0)