def unlock_dataset(name, options=None): payload = { 'id': name, 'unlock_options': { 'recursive': True, 'datasets': [ { 'name': name, 'passphrase': 'passphrase' } ], **(options or {}), } } results = POST('/pool/dataset/unlock/', payload) assert results.status_code == 200, results.text job_id = results.json() job_status = wait_on_job(job_id, 120) assert job_status['state'] == 'SUCCESS', str(job_status['results']) assert job_status['results']['result']['unlocked'] == [name], str(job_status['results'])
def test_39_set_truecommand_ix_chart_hostPathVolumes(request): depends(request, ['tc_chart_release', 'hostpath-dataset']) global payload payload = { 'values': { 'hostPathVolumes': [ { 'hostPath': f'/mnt/{pool_name}/tc-hostpath', 'mountPath': '/mnt', 'readOnly': True } ] } } results = PUT(f'/chart/release/id/{tc_release_id}/', payload) assert results.status_code == 200, results.text assert isinstance(results.json(), int), results.text job_status = wait_on_job(results.json(), 300) assert job_status['state'] == 'SUCCESS', str(job_status['results']) time.sleep(1)
def test_079_try_to_unlock_the_child_of_lock_parent_encrypted_root(request): depends(request, ['CREATED_POOL']) payload = { 'id': child_dataset, 'unlock_options': { 'recursive': True, 'datasets': [{ 'name': child_dataset, 'passphrase': 'my_passphrase2' }] } } results = POST('/pool/dataset/unlock/', payload) assert results.status_code == 200, results.text job_id = results.json() job_status = wait_on_job(job_id, 120) assert job_status['state'] == 'FAILED', str(job_status['results']) assert f'{child_dataset} has locked parents' in str( job_status['results']), str(job_status['results']) assert job_status['results']['result'] is None, str(job_status['results'])
def test_08_verify_traverse_to_child_dataset(request): depends(request, ["RECURSIVE_PREPARED"]) result = POST( f'/pool/dataset/id/{dataset_url}/permission/', { 'acl': [], 'mode': 777, 'group': 'nogroup', 'user': '******', 'options': {'recursive': True, 'traverse': True} } ) assert result.status_code == 200, result.text JOB_ID = result.json() job_status = wait_on_job(JOB_ID, 180) assert job_status['state'] == 'SUCCESS', str(job_status['results']) results = POST('/filesystem/stat/', f'/mnt/{MODE_SUBDATASET}') assert results.status_code == 200, results.text current_mode = results.json()['mode'] assert f"{stat.S_IMODE(current_mode):03o}" == "777", results.text
def test_027_unlock_passphrase_encrypted_datasets_with_wrong_passphrase( request): depends(request, ['CREATED_POOL']) payload = { 'id': dataset, 'unlock_options': { 'recursive': True, 'datasets': [{ 'name': dataset, 'passphrase': 'bad_passphrase' }] } } results = POST('/pool/dataset/unlock/', payload) assert results.status_code == 200, results.text job_id = results.json() job_status = wait_on_job(job_id, 120) assert job_status['state'] == 'SUCCESS', str(job_status['results']) assert job_status['results']['result']['failed'][dataset][ 'error'] == 'Invalid Key', str(job_status['results'])
def test_14_recursive_with_traverse(request): """ This test verifies that setting `traverse = True` will allow setacl operation to cross mountpoints. """ depends(request, ["HAS_POSIX_ACLS"]) payload = { 'gid': 65534, 'uid': 65534, 'path': f'/mnt/{ACLTEST_DATASET}', 'dacl': ACLBrand.ACCESS.getacl(), 'acltype': 'POSIX1E', 'options': { 'recursive': True, 'traverse': True }, } default = ACLBrand.DEFAULT.getacl({ "READ": True, "WRITE": True, "EXECUTE": True }) payload['dacl'].extend(default) result = POST('/filesystem/setacl/', payload) assert result.status_code == 200, result.text JOB_ID = result.json() job_status = wait_on_job(JOB_ID, 180) assert job_status['state'] == 'SUCCESS', str(job_status['results']) results = POST('/filesystem/getacl/', {'path': f'/mnt/{ACLTEST_SUBDATASET}'}) assert results.status_code == 200, results.text new_acl = results.json() assert new_acl['trivial'] == False, results.text # Verify that user was changed assert results.json()['uid'] == 65534, results.text
def dataset(name, options=None): assert "/" not in name dataset = f"{pool_name}/{name}" result = POST("/pool/dataset/", {"name": dataset, **(options or {})}) assert result.status_code == 200, result.text result = POST("/filesystem/setperm/", { 'path': f"/mnt/{dataset}", "mode": "777" }) assert result.status_code == 200, result.text job_status = wait_on_job(result.json(), 180) assert job_status["state"] == "SUCCESS", str(job_status["results"]) try: yield dataset finally: result = DELETE(f"/pool/dataset/id/{urllib.parse.quote(dataset, '')}/") assert result.status_code == 200, result.text
def test_08_set_perms(request, perm): """ Validation that READ, WRITE, EXECUTE are set correctly via endpoint. OTHER entry is used for this purpose. """ depends(request, ["HAS_POSIX_ACLS"]) payload = { 'path': f'/mnt/{ACLTEST_DATASET}', 'dacl': ACLBrand.ACCESS.getacl(), 'acltype': 'POSIX1E' } payload['dacl'][2]['perms'][perm] = True result = POST('/filesystem/setacl/', payload) assert result.status_code == 200, result.text JOB_ID = result.json() job_status = wait_on_job(JOB_ID, 180) assert job_status['state'] == 'SUCCESS', str(job_status['results']) results = POST('/filesystem/getacl/', {'path': f'/mnt/{ACLTEST_DATASET}'}) assert results.status_code == 200, results.text received_perms = results.json()['acl'][2]['perms'] assert received_perms[perm], results.text
def test_001_create_a_normal_pool(request): depends(request, ['pool_04'], scope='session') global pool_id, pool_disks # Get one disk for encryption testing pool_disks = [POST('/disk/get_unused/', controller_a=ha).json()[0]['name']] payload = { 'name': encrypted_pool_name, 'encryption': False, 'topology': { 'data': [{ 'type': 'STRIPE', 'disks': pool_disks }], }, "allow_duplicate_serials": True, } results = POST('/pool/', payload) assert results.status_code == 200, results.text job_id = results.json() job_status = wait_on_job(job_id, 240) assert job_status['state'] == 'SUCCESS', str(job_status['results']) pool_id = job_status['results']['result']['id']
def test_04_verify_setting_mode_bits_nonrecursive(request, mode_bit): """ This test iterates through possible POSIX permissions bits and verifies that they are properly set on the remote server. """ depends(request, ["IS_TRIVIAL"]) new_mode = f"{MODE[mode_bit]:03o}" result = POST(f'/pool/dataset/id/{dataset_url}/permission/', { 'acl': [], 'mode': new_mode, 'group': group, 'user': '******' }) assert result.status_code == 200, result.text JOB_ID = result.json() job_status = wait_on_job(JOB_ID, 180) assert job_status['state'] == 'SUCCESS', str(job_status['results']) results = POST('/filesystem/stat/', f'/mnt/{MODE_DATASET}') assert results.status_code == 200, results.text server_mode = f"{stat.S_IMODE(results.json()['mode']):03o}" assert new_mode == server_mode, results.text
def test_11_set_advanced_flagset(request, flag): depends(request, ["HAS_NFS4_ACLS"]) payload = {'path': f'/mnt/{ACLTEST_DATASET}', 'simplified': False} default_acl[0]['flags'] = base_flagset.copy() default_acl[0]['flags'][flag] = True if flag in ['INHERIT_ONLY', 'NO_PROPAGATE_INHERIT']: default_acl[0]['flags']['DIRECTORY_INHERIT'] = True result = POST(f'/pool/dataset/id/{dataset_url}/permission/', { 'acl': default_acl, 'group': group, 'user': '******' }) assert result.status_code == 200, result.text JOB_ID = result.json() job_status = wait_on_job(JOB_ID, 180) assert job_status['state'] == 'SUCCESS', str(job_status['results']) results = POST('/filesystem/getacl/', payload) assert results.status_code == 200, results.text requested_flags = default_acl[0]['flags'] received_flags = results.json()['acl'][0]['flags'] assert received_flags == requested_flags, results.text
def test_42_creating_a_key_encrypted_pool(): global pool_id payload = { 'name': pool_name, 'encryption': True, 'encryption_options': { 'algorithm': 'AES-128-CCM', 'key': pool_token_hex, }, 'topology': { 'data': [{ 'type': 'STRIPE', 'disks': disk_pool }], } } results = POST('/pool/', payload) assert results.status_code == 200, results.text job_id = results.json() job_status = wait_on_job(job_id, 120) assert job_status['state'] == 'SUCCESS', str(job_status['results']) pool_id = job_status['results']['result']['id']
def test_17_test_file_other_bits_function_allow(mode_bit, request): """ Verify mode behavior correct when it's the only bit set. """ depends(request, ["USER_CREATED", "ssh_password"], scope="session") new_mode = MODE[mode_bit] result = POST( '/filesystem/setperm/', { 'path': f'/mnt/{MODE_DATASET}/canary', 'mode': f'{new_mode:03o}', 'gid': 0, 'uid': 0, }) assert result.status_code == 200, result.text JOB_ID = result.json() job_status = wait_on_job(JOB_ID, 180) assert job_status['state'] == 'SUCCESS', str(job_status['results']) if job_status['state'] != 'SUCCESS': return file_mode_check(mode_bit)
def test_30_creating_home_dataset(request): """ SMB share_type is selected for this test so that we verify that ACL is being stripped properly from the newly-created home directory. """ depends(request, ["pool_04"], scope="session") payload = { "name": dataset, "share_type": "SMB" } results = POST("/pool/dataset/", payload) assert results.status_code == 200, results.text results = POST( f'/pool/dataset/id/{dataset_url}/permission/', { 'acl': home_acl, } ) assert results.status_code == 200, results.text perm_job = results.json() job_status = wait_on_job(perm_job, 180) assert job_status['state'] == 'SUCCESS', str(job_status['results'])
def test_68_unlock_parent_dataset_with_child_recursively(): payload = { 'id': dataset, 'unlock_options': { 'recursive': True, 'datasets': [{ 'name': dataset, 'passphrase': 'my_passphrase' }, { 'name': child_dataset, 'passphrase': 'my_passphrase2' }] } } results = POST('/pool/dataset/unlock/', payload) assert results.status_code == 200, results.text job_id = results.json() job_status = wait_on_job(job_id, 120) assert job_status['state'] == 'SUCCESS', str(job_status['results']) assert job_status['results']['result']['unlocked'] == [ dataset, child_dataset ], str(job_status['results'])
def test_13_create_ix_chart_chart_release_with(request): depends(request, ['pull_public_image']) global tc_release_id payload = { 'catalog': 'OFFICIAL', 'item': 'ix-chart', 'release_name': 'truecommand', 'train': 'charts', 'values': { 'workloadType': 'Deployment', 'image': { 'repository': 'ixsystems/truecommand', 'tag': 'latest' }, 'hostNetwork': True } } results = POST('/chart/release/', payload) assert results.status_code == 200, results.text assert isinstance(results.json(), int), results.text job_status = wait_on_job(results.json(), 300) assert job_status['state'] == 'SUCCESS', str(job_status['results']) tc_release_id = job_status['results']['result']['id']
def test_09_set_basic_flagsets(request, flagset): depends(request, ["HAS_NFS4_ACLS"]) payload = { 'path': f'/mnt/{ACLTEST_DATASET}', 'simplified': True } default_acl[0]['flags']['BASIC'] = flagset result = POST( f'/pool/dataset/id/{dataset_url}/permission/', { 'acl': default_acl, 'group': group, 'user': '******' } ) assert result.status_code == 200, result.text JOB_ID = result.json() job_status = wait_on_job(JOB_ID, 180) assert job_status['state'] == 'SUCCESS', str(job_status['results']) results = POST('/filesystem/getacl/', payload) assert results.status_code == 200, results.text requested_flags = default_acl[0]['flags'] received_flags = results.json()['acl'][0]['flags'] assert received_flags == requested_flags, results.text
def test_004_test_flags(request): """ This test creates a temporary dataset / SMB share, then iterates through all the possible inheritance flags setting local FS ace for each of them and verifies that correct NT ACL bit gets toggled when viewed through SMB protocol. """ depends(request, ["SMB_SERVICE_STARTED", "pool_04"], scope="session") ds = 'nfs4acl_flags_smb' path = f'/mnt/{pool_name}/{ds}' with smb_dataset(ds): with smb_share(path, {"name": "FLAGS"}): result = POST('/filesystem/getacl/', { 'path': path, 'simplified': False }) assert result.status_code == 200, result.text the_acl = result.json()['acl'] new_entry = { 'perms': permset, 'flags': flagset, 'id': 666, 'type': 'ALLOW', 'tag': 'USER' } the_acl.insert(0, new_entry) result = POST("/filesystem/setacl/", { 'path': path, "dacl": the_acl }) assert result.status_code == 200, result.text job_status = wait_on_job(result.json(), 180) assert job_status["state"] == "SUCCESS", str(job_status["results"]) iter_flagset(path, "FLAGS", the_acl)
def test_06_verify_setting_mode_bits_recursive_no_traverse(request, mode_bit): """ Perform recursive permissions change and verify new mode written to files and subdirectories. """ depends(request, ["RECURSIVE_PREPARED"]) new_mode = f"{MODE[mode_bit]:03o}" result = POST( f'/pool/dataset/id/{dataset_url}/permission/', { 'acl': [], 'mode': new_mode, 'group': group, 'user': '******', 'options': { 'recursive': True } }) assert result.status_code == 200, result.text JOB_ID = result.json() job_status = wait_on_job(JOB_ID, 180) assert job_status['state'] == 'SUCCESS', str(job_status['results']) results = POST('/filesystem/stat/', f'/mnt/{MODE_DATASET}') assert results.status_code == 200, results.text server_mode = f"{stat.S_IMODE(results.json()['mode']):03o}" assert new_mode == server_mode, results.text results = POST('/filesystem/stat/', f'/mnt/{MODE_DATASET}/dir1/dir2') assert results.status_code == 200, results.text server_mode = f"{stat.S_IMODE(results.json()['mode']):03o}" assert new_mode == server_mode, results.text results = POST('/filesystem/stat/', f'/mnt/{MODE_DATASET}/dir1/dir2/testfile') assert results.status_code == 200, results.text server_mode = f"{stat.S_IMODE(results.json()['mode']):03o}" assert new_mode == server_mode, results.text
def test_20_test_file_other_bits_xor(mode_bit, request): """ Verify mode behavior correct when it's the only bit set. """ depends(request, ["USER_CREATED"]) new_mode = stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO new_mode = new_mode ^ MODE[mode_bit] result = POST( '/filesystem/setperm/', { 'path': f'/mnt/{MODE_DATASET}/canary', 'mode': f'{new_mode:03o}', 'gid': 0, 'uid': 0 }) assert result.status_code == 200, result.text JOB_ID = result.json() job_status = wait_on_job(JOB_ID, 180) assert job_status['state'] == 'SUCCESS', str(job_status['results']) if job_status['state'] != 'SUCCESS': return file_mode_check_xor(mode_bit)
def test_11_non_recursive_acl_strip(request): """ Verify that non-recursive ACL strip works correctly. We do this by checking result of subsequent getacl request on the path (it should report that it is "trivial"). """ depends(request, ["HAS_POSIX_ACLS"]) payload = { 'path': f'/mnt/{ACLTEST_DATASET}', 'dacl': [], 'acltype': 'POSIX1E', 'options': {'stripacl': True}, } result = POST('/filesystem/setacl/', payload) assert result.status_code == 200, result.text JOB_ID = result.json() job_status = wait_on_job(JOB_ID, 180) assert job_status['state'] == 'SUCCESS', str(job_status['results']) results = POST('/filesystem/getacl/', {'path': f'/mnt/{ACLTEST_DATASET}'}) assert results.status_code == 200, results.text new_acl = results.json() assert new_acl['trivial'], results.text
def test_049_creating_a_key_encrypted_pool(request): depends(request, ['CREATED_POOL']) global pool_id payload = { 'name': encrypted_pool_name, 'encryption': True, 'encryption_options': { 'algorithm': 'AES-128-CCM', 'key': pool_token_hex, }, 'topology': { 'data': [{ 'type': 'STRIPE', 'disks': pool_disks }], }, "allow_duplicate_serials": True, } results = POST('/pool/', payload) assert results.status_code == 200, results.text job_id = results.json() job_status = wait_on_job(job_id, 240) assert job_status['state'] == 'SUCCESS', str(job_status['results']) pool_id = job_status['results']['result']['id']
def test_10_set_advanced_permset(request, perm): depends(request, ["HAS_NFS4_ACLS"]) payload = {'path': f'/mnt/{ACLTEST_DATASET}', 'simplified': False} for key in ['perms', 'flags']: if default_acl[0][key].get('BASIC'): default_acl[0][key].pop('BASIC') default_acl[0]['flags'] = base_flagset.copy() default_acl[0]['perms'] = base_permset.copy() default_acl[0]['perms'][perm] = True result = POST(f'/pool/dataset/id/{dataset_url}/permission/', { 'acl': default_acl, 'group': group, 'user': '******' }) assert result.status_code == 200, result.text JOB_ID = result.json() job_status = wait_on_job(JOB_ID, 180) assert job_status['state'] == 'SUCCESS', str(job_status['results']) results = POST('/filesystem/getacl/', payload) assert results.status_code == 200, results.text requested_perms = default_acl[0]['perms'] received_perms = results.json()['acl'][0]['perms'] assert requested_perms == received_perms, results.text
def test_06_verify_list_of_available_plugins_job_id_is_successfull(request): depends(request, ["pool_04"], scope="session") global job_results job_status = wait_on_job(JOB_ID, 180) assert job_status['state'] == 'SUCCESS', str(job_status['results']) job_results = job_status['results']
def test_34_verify_transmission_plugin_job_is_successfull(request): depends(request, ["pool_04"], scope="session") job_status = wait_on_job(JOB_ID, 600) assert job_status['state'] == 'SUCCESS', str(job_status['results'])
def test_25_wait_for_transmission_plugin_to_be_down(request): depends(request, ["pool_04"], scope="session") job_status = wait_on_job(JOB_ID, 15) assert job_status['state'] == 'SUCCESS', str(job_status['results']) results = GET('/plugin/id/transmission/') assert results.json()['state'] == 'down', results.text
def test_04_verify_the_job_id_is_successful(request): depends(request, ["AD_ENABLED"]) job_status = wait_on_job(job_id, 180) assert job_status['state'] == 'SUCCESS', str(job_status['results'])
def test_004_verify_the_job_id_is_successfull(request): depends(request, ["pool_04", "smb_001", "smb_003"], scope="session") job_status = wait_on_job(job_id, 180) assert job_status['state'] == 'SUCCESS', str(job_status['results'])
def test_10_set_tags_default(request, tag): """ Validation that entries for all tag types can be set correctly. In case of USER_OBJ, GROUP_OBJ, and OTHER, the existing entry is modified to match our test permset. USER and GROUP (named) entries are set for id 1000 (user / group need not exist for this to succeed). Named entries require an additional mask entry. This particular test covers "default" entries in POSIX1E ACL. """ depends(request, ["HAS_POSIX_ACLS"]) test_permset = {"READ": True, "WRITE": False, "EXECUTE": True} must_add = True payload = { 'path': f'/mnt/{ACLTEST_DATASET}', 'dacl': ACLBrand.ACCESS.getacl(), 'acltype': 'POSIX1E', } default = ACLBrand.DEFAULT.getacl() for entry in default: if entry['tag'] == tag: entry['perms'] = test_permset must_add = False if must_add: new_entry = { 'tag': tag, 'perms': test_permset, 'id': 1000, 'default': True, } if tag == 'MASK': new_entry['id'] = -1 # POSIX ACLs are quite particular about # ACE ordering. We do this on backend. # MASK comes before OTHER. default.insert(2, new_entry) elif tag == 'USER': default.insert(1, new_entry) elif tag == 'GROUP': default.insert(2, new_entry) if tags[tag]['mask_required']: new_entry = { 'tag': "MASK", 'perms': test_permset, 'id': -1, 'default': True, } default.insert(3, new_entry) payload['dacl'].extend(default) result = POST('/filesystem/setacl/', payload) assert result.status_code == 200, results.text JOB_ID = result.json() job_status = wait_on_job(JOB_ID, 180) assert job_status['state'] == 'SUCCESS', str(job_status['results']) results = POST('/filesystem/getacl/', {'path': f'/mnt/{ACLTEST_DATASET}'}) assert results.status_code == 200, results.text new_acl = results.json() assert payload['dacl'] == new_acl['acl'], results.text assert new_acl['trivial'] == False, results.text
def test_003_verify_the_job_id_is_successful(request): depends(request, ["SMB_DATASET_CREATED"]) job_status = wait_on_job(job_id, 180) assert job_status['state'] == 'SUCCESS', str(job_status['results'])