|
29 | 29 |
|
30 | 30 | import os |
31 | 31 | import time |
| 32 | +import unittest |
32 | 33 |
|
33 | | -from tests.support import MigTestCase, ensure_dirs_exist, testmain |
34 | 34 | from mig.shared.base import client_id_dir |
35 | 35 | from mig.shared.serial import dump |
36 | | -from mig.shared.vgrid import vgrid_is_default, vgrid_exists, vgrid_list_vgrids, \ |
37 | | - vgrid_add_entities, vgrid_remove_entities, vgrid_settings, \ |
38 | | - vgrid_is_owner_or_member, vgrid_is_owner, vgrid_is_member, \ |
39 | | - vgrid_list, vgrid_set_entities, get_vgrid_workflow_jobs, vgrid_add_owners, \ |
40 | | - vgrid_add_members, vgrid_add_workflow_jobs |
| 36 | +from mig.shared.vgrid import get_vgrid_workflow_jobs, legacy_main, \ |
| 37 | + vgrid_add_entities, vgrid_add_members, vgrid_add_owners, \ |
| 38 | + vgrid_add_workflow_jobs, vgrid_allow_restrict_write, vgrid_exists, \ |
| 39 | + vgrid_is_default, vgrid_is_member, vgrid_is_owner, \ |
| 40 | + vgrid_is_owner_or_member, vgrid_list, vgrid_list_parents, \ |
| 41 | + vgrid_list_subvgrids, vgrid_list_vgrids, vgrid_match_resources, \ |
| 42 | + vgrid_nest_sep, vgrid_remove_entities, vgrid_restrict_write, \ |
| 43 | + vgrid_set_entities, vgrid_settings |
| 44 | +from tests.support import MigTestCase, ensure_dirs_exist, testmain |
41 | 45 |
|
42 | 46 |
|
43 | 47 | class TestMigSharedVgrid(MigTestCase): |
@@ -197,11 +201,13 @@ def test_vgrid_settings_inheritance(self): |
197 | 201 | def test_vgrid_permission_checks(self): |
198 | 202 | """Test owner/member permission verification""" |
199 | 203 | # Setup owners and members |
200 | | - vgrid_add_entities(self.configuration, self.test_vgrid, |
201 | | - 'owners', [self.TEST_OWNER_DN]) |
| 204 | + added, msg = vgrid_add_entities(self.configuration, self.test_vgrid, |
| 205 | + 'owners', [self.TEST_OWNER_DN]) |
| 206 | + self.assertTrue(added, msg) |
202 | 207 | time.sleep(0.1) |
203 | | - vgrid_add_entities(self.configuration, self.test_vgrid, |
204 | | - 'members', [self.TEST_MEMBER_DN]) |
| 208 | + added, msg = vgrid_add_entities(self.configuration, self.test_vgrid, |
| 209 | + 'members', [self.TEST_MEMBER_DN]) |
| 210 | + self.assertTrue(added, msg) |
205 | 211 | time.sleep(0.1) |
206 | 212 |
|
207 | 213 | # Verify owner permissions |
@@ -230,14 +236,8 @@ def test_workflow_job_management(self): |
230 | 236 | self.TEST_OWNER_DIR) |
231 | 237 | ensure_dirs_exist(job_dir) |
232 | 238 | job_path = os.path.join(job_dir, '%s.mRSL' % self.TEST_JOB_ID) |
233 | | - # with open(job_path, 'w') as job_fd: |
234 | | - # job_fd.write('\n') |
235 | 239 | dump({'job_id': self.TEST_JOB_ID, 'EXECUTE': 'uptime'}, job_path) |
236 | 240 |
|
237 | | - print("DEBUG: wrote %r" % job_path) |
238 | | - # vgrid_add_workflow_jobs(self.configuration, self.test_vgrid, |
239 | | - # [self.TEST_JOB_ID]) |
240 | | - |
241 | 241 | # Add job |
242 | 242 | status, msg = vgrid_add_entities(self.configuration, self.test_vgrid, |
243 | 243 | 'jobqueue', [job_entry]) |
@@ -282,6 +282,155 @@ def test_workflow_job_management(self): |
282 | 282 | self.assertTrue(status) |
283 | 283 | self.assertEqual(len(jobs), 0) |
284 | 284 |
|
| 285 | + def test_vgrid_list_subvgrids(self): |
| 286 | + """Test retrieving subvgrids of given vgrid""" |
| 287 | + status, subvgrids = vgrid_list_subvgrids(self.test_vgrid, |
| 288 | + self.configuration) |
| 289 | + self.assertTrue(status) |
| 290 | + self.assertEqual(subvgrids, [self.test_subvgrid]) |
| 291 | + |
| 292 | + def test_vgrid_list_parents(self): |
| 293 | + """Test listing parent vgrids (root first)""" |
| 294 | + parents = vgrid_list_parents(self.test_subvgrid, self.configuration) |
| 295 | + expected = [self.test_vgrid] |
| 296 | + self.assertEqual(parents, expected) |
| 297 | + |
| 298 | + def test_vgrid_match_resources(self): |
| 299 | + """Test resource filtering for vgrid""" |
| 300 | + test_resources = ['res1', 'res2', 'invalid_res', self.TEST_RESOURCE_DN] |
| 301 | + added, msg = vgrid_add_entities(self.configuration, self.test_vgrid, |
| 302 | + 'resources', [self.TEST_RESOURCE_DN]) |
| 303 | + self.assertTrue(added, msg) |
| 304 | + |
| 305 | + matched = vgrid_match_resources(self.test_vgrid, test_resources, |
| 306 | + self.configuration) |
| 307 | + self.assertEqual(matched, [self.TEST_RESOURCE_DN]) |
| 308 | + |
| 309 | + # TODO: adjust API to allow enabling the next test |
| 310 | + @unittest.skipIf(True, "requires read-only mount") |
| 311 | + def test_vgrid_allow_restrict_write(self): |
| 312 | + """Test write restriction validation logic""" |
| 313 | + # Create parent-child structure |
| 314 | + parent_write_setting = [('write_shared_files', 'none')] |
| 315 | + added, msg = vgrid_add_entities(self.configuration, self.test_vgrid, |
| 316 | + 'settings', parent_write_setting) |
| 317 | + self.assertTrue(added, msg) |
| 318 | + |
| 319 | + # Child tries to set write_shared_files to "members" |
| 320 | + result = vgrid_allow_restrict_write(self.test_subvgrid, 'members', |
| 321 | + self.configuration, |
| 322 | + auto_migrate=True) |
| 323 | + self.assertFalse(result) |
| 324 | + |
| 325 | + # Valid case: parent allows writes, child sets to "none" |
| 326 | + parent_write_setting = [('write_shared_files', 'members')] |
| 327 | + vgrid_set_entities(self.configuration, self.test_vgrid, |
| 328 | + 'settings', parent_write_setting, True) |
| 329 | + |
| 330 | + result = vgrid_allow_restrict_write(self.test_subvgrid, 'none', |
| 331 | + self.configuration, |
| 332 | + auto_migrate=True) |
| 333 | + self.assertTrue(result) |
| 334 | + |
| 335 | + # TODO: adjust API to allow enabling the next test |
| 336 | + @unittest.skipIf(True, "requires read-only mount") |
| 337 | + def test_vgrid_restrict_write(self): |
| 338 | + """Test write restriction enforcement""" |
| 339 | + # Setup test share |
| 340 | + test_share = os.path.join(self.configuration.vgrid_files_home, |
| 341 | + self.test_vgrid) |
| 342 | + ensure_dirs_exist(test_share) |
| 343 | + |
| 344 | + # Migrate to restricted mode |
| 345 | + result = vgrid_restrict_write(self.test_vgrid, 'none', |
| 346 | + self.configuration, auto_migrate=True) |
| 347 | + self.assertTrue(result) |
| 348 | + |
| 349 | + # Verify symlink points to readonly |
| 350 | + flat_vgrid = self.test_vgrid.replace('/', vgrid_nest_sep) |
| 351 | + read_path = os.path.join(self.configuration.vgrid_files_readonly, |
| 352 | + flat_vgrid) |
| 353 | + self.assertEqual(os.path.realpath(test_share), |
| 354 | + os.path.realpath(read_path)) |
| 355 | + |
| 356 | + def test_vgrid_settings_scopes(self): |
| 357 | + """Test different vgrid settings lookup scopes""" |
| 358 | + # Local settings only |
| 359 | + local_settings = [('vgrid_name', self.test_subvgrid), |
| 360 | + ('description', 'test subvgrid'), |
| 361 | + ('write_shared_files', 'members'), |
| 362 | + ] |
| 363 | + added, msg = vgrid_add_entities(self.configuration, self.test_subvgrid, |
| 364 | + 'settings', local_settings) |
| 365 | + self.assertTrue(added, msg) |
| 366 | + |
| 367 | + # Check recursive vs direct |
| 368 | + status, recursive_settings = vgrid_settings( |
| 369 | + self.test_subvgrid, self.configuration, recursive=True, as_dict=True) |
| 370 | + self.assertTrue(status) |
| 371 | + status, direct_settings = vgrid_settings( |
| 372 | + self.test_subvgrid, self.configuration, recursive=False, as_dict=True) |
| 373 | + self.assertTrue(status) |
| 374 | + self.assertEqual(direct_settings['description'], 'test subvgrid') |
| 375 | + self.assertIn('write_shared_files', recursive_settings) # Inherited |
| 376 | + |
| 377 | + def test_vgrid_add_owner_rank(self): |
| 378 | + """Test owner ranking/ordering functionality""" |
| 379 | + new_owner = '/C=DK/CN=New Owner' |
| 380 | + added, msg = vgrid_add_owners( |
| 381 | + self.configuration, |
| 382 | + self.test_vgrid, |
| 383 | + [new_owner], |
| 384 | + rank=0 # Add as first owner |
| 385 | + ) |
| 386 | + self.assertTrue(added, msg) |
| 387 | + |
| 388 | + owners = vgrid_list(self.test_vgrid, 'owners', self.configuration)[1] |
| 389 | + self.assertEqual(owners[0], new_owner) |
| 390 | + |
| 391 | + # TODO: adjust API to allow enabling the next test |
| 392 | + @unittest.skipIf(True, "requires tweaking of funcion") |
| 393 | + def test_workflow_job_priority(self): |
| 394 | + """Test workflow job queue ordering and limits""" |
| 395 | + # Create max jobs + 1 |
| 396 | + job_entries = [ |
| 397 | + {'client_id': self.TEST_OWNER_DN, 'job_id': str(i)} |
| 398 | + for i in range(101) |
| 399 | + ] |
| 400 | + added, msg = vgrid_add_workflow_jobs( |
| 401 | + self.configuration, |
| 402 | + self.test_vgrid, |
| 403 | + job_entries |
| 404 | + ) |
| 405 | + self.assertTrue(added, msg) |
| 406 | + |
| 407 | + status, jobs = vgrid_list( |
| 408 | + self.test_vgrid, 'jobqueue', self.configuration) |
| 409 | + self.assertTrue(status) |
| 410 | + # Should stay at max 100 by removing oldest |
| 411 | + self.assertEqual(len(jobs), 100) |
| 412 | + self.assertEqual(jobs[-1]['job_id'], '100') # Newest at end |
| 413 | + |
| 414 | + |
| 415 | +class TestMigSharedVgrid__main(MigTestCase): |
| 416 | + """Unit tests for vgrid self-checks""" |
| 417 | + |
| 418 | + def test_existing_main(self): |
| 419 | + def raise_on_error_exit(exit_code): |
| 420 | + if exit_code != 0: |
| 421 | + if raise_on_error_exit.last_print is not None: |
| 422 | + identifying_message = raise_on_error_exit.last_print |
| 423 | + else: |
| 424 | + identifying_message = 'unknown' |
| 425 | + raise AssertionError( |
| 426 | + 'failure in unittest/testcore: %s' % (identifying_message,)) |
| 427 | + raise_on_error_exit.last_print = None |
| 428 | + |
| 429 | + def record_last_print(value): |
| 430 | + raise_on_error_exit.last_print = value |
| 431 | + |
| 432 | + legacy_main(_exit=raise_on_error_exit, _print=record_last_print) |
| 433 | + |
285 | 434 |
|
286 | 435 | if __name__ == '__main__': |
287 | 436 | testmain() |
0 commit comments