def testGetDevList(t, env): """Check devlist FLAGS: pnfs CODE: GETDLIST1 """ # Make sure E_ID returns MDS capabilities c1 = env.c1.new_client(env.testname(t), flags=EXCHGID4_FLAG_USE_PNFS_MDS) if not c1.flags & EXCHGID4_FLAG_USE_PNFS_MDS: fail("Server did not set EXCHGID4_FLAG_USE_PNFS_MDS") sess = c1.create_session() # Test that fs handles block layouts ops = use_obj(env.opts.path) + [op.getattr(1<<FATTR4_FS_LAYOUT_TYPE)] res = sess.compound(ops) check(res) if FATTR4_FS_LAYOUT_TYPE not in res.resarray[-1].obj_attributes: fail("fs_layout_type not available") for lo_type in res.resarray[-1].obj_attributes[FATTR4_FS_LAYOUT_TYPE]: # Send GETDEVICELIST ops = use_obj(env.opts.path) + [op.getdevicelist(lo_type, 0xffffffff, 0, "")] res = sess.compound(ops) check(res) # STUB - check block stuff dev_list = res.resarray[-1].gdlr_deviceid_list print dev_list
def testAnonReadWrite(t, env): """Do a simple READ and WRITE using anonymous stateid FLAGS: open all CODE: OPEN31 """ sess1 = env.c1.new_client_session(env.testname(t)) owner = open_owner4(0, "My Open Owner") res = create_file(sess1, env.testname(t)) check(res) expect(res, seqid=1) fh = res.resarray[-1].object data = "write test data" stateid = res.resarray[-2].stateid res = close_file(sess1, fh, stateid=stateid) check(res) res = sess1.compound([op.putfh(fh), op.write(nfs4lib.state00, 5, FILE_SYNC4, data)]) check(res) res = sess1.compound([op.putfh(fh), op.read(nfs4lib.state00, 0, 1000)]) check(res) if not res.resarray[-1].eof: fail("EOF not set on read") desired = "\0"*5 + data if res.resarray[-1].data != desired: fail("Expected %r, got %r" % (desired, res.resarray[-1].data))
def testOPENClaimFH(t, env): """OPEN file with claim_type is CLAIM_FH FLAGS: open all CODE: OPEN7 """ sess1 = env.c1.new_client_session(env.testname(t)) res = create_file(sess1, env.testname(t)) check(res) fh = res.resarray[-1].object stateid = res.resarray[-2].stateid res = close_file(sess1, fh, stateid=stateid) check(res) claim = open_claim4(CLAIM_FH) how = openflag4(OPEN4_NOCREATE) oowner = open_owner4(0, "My Open Owner 2") open_op = op.open(0, OPEN4_SHARE_ACCESS_BOTH, OPEN4_SHARE_DENY_NONE, oowner, how, claim) res = sess1.compound([op.putfh(fh), open_op]) check(res) stateid = res.resarray[-1].stateid stateid.seqid = 0 data = "write test data" res = sess1.compound([op.putfh(fh), op.write(stateid, 5, FILE_SYNC4, data)]) check(res) res = sess1.compound([op.putfh(fh), op.read(stateid, 0, 1000)]) check(res) if not res.resarray[-1].eof: fail("EOF not set on read") desired = "\0"*5 + data if res.resarray[-1].data != desired: fail("Expected %r, got %r" % (desired, res.resarray[-1].data))
def testGetDevInfo(t, env): """Check devlist FLAGS: pnfs DEPEND: GETDLIST1 CODE: GETDINFO1 """ sess = env.c1.new_pnfs_client_session(env.testname(t)) # Test that fs handles block layouts ops = use_obj(env.opts.path) + [op.getattr(1<<FATTR4_FS_LAYOUT_TYPES)] res = sess.compound(ops) check(res) if FATTR4_FS_LAYOUT_TYPES not in res.resarray[-1].obj_attributes: fail("fs_layout_type not available") for lo_type in res.resarray[-1].obj_attributes[FATTR4_FS_LAYOUT_TYPES]: # Send GETDEVICELIST lo_type = LAYOUT4_BLOCK_VOLUME ops = use_obj(env.opts.path) + [op.getdevicelist(lo_type, 0xffffffff, 0, "")] res = sess.compound(ops) check(res) dev_list = res.resarray[-1].gdlr_deviceid_list p = BlockUnpacker("") for dev_id in dev_list: ops = use_obj(env.opts.path) + [op.getdeviceinfo(dev_id, lo_type, 0xffffffff, 0)] res = sess.compound(ops) check(res) if lo_type==LAYOUT4_BLOCK_VOLUME: p.reset(res.resarray[-1].da_addr_body) decode = p.unpack_pnfs_block_deviceaddr4() p.done() print decode
def testReplayCache002(t, env): """Send two successful non-idempotent compounds with same seqid FLAGS: sequence all CODE: SEQ9b """ sess1 = env.c1.new_client_session(env.testname(t)) res = create_file(sess1, "%s_1" % env.testname(t)) fh = res.resarray[-1].object stateid = res.resarray[-2].stateid check(res) ops = env.home + [op.savefh(),\ op.rename("%s_1" % env.testname(t), "%s_2" % env.testname(t))] res1 = sess1.compound(ops, cache_this=True) check(res1) res2 = sess1.compound(ops, seq_delta=0) check(res2) res1.tag = res2.tag = "" if not nfs4lib.test_equal(res1, res2): fail("Replay results not equal") # Cleanup res = sess1.compound([op.putfh(fh), op.close(0, stateid)]) check(res)
def testCallbackProgram(t, env): """Check server can handle random transient program number FLAGS: ganesha CODE: CSESS20 """ cb_occurred = threading.Event() transient = 0x40000004 def mycheck(prog): print "Got call using prog=0x%x" % prog cb_occurred.prog = prog cb_occurred.set() return True; orig = env.c1._check_program try: env.c1._check_program = mycheck c = env.c1.new_client(env.testname(t)) sess = c.create_session(prog=transient) cb_occurred.wait(10) if not cb_occurred.isSet(): fail("No CB_NULL sent") if cb_occurred.prog != transient: fail("Expected cb progam 0x%x, got 0x%x" % (transient, cb_occurred.prog)) finally: env.c1._check_program = orig
def testOpenZeroes(t, env): """Test client is zeroing out values on open FLAGS: open all CODE: OPEN1 """ """ cd $HOME touch foo """ foo = env.testname(t) env.control_reset() # cd $HOME os.chdir(env.home) # touch foo env.control_record(foo) fd = open(foo, "w") env.control_pause() calls = env.control_grab_calls(foo) fd.close() # Now analyse RPC calls the client made for op in env.find_op(OP_OPEN, calls): if op.seqid != 0: fail("seqid !=0") if op.owner.clientid != 0: fail("clientid != 0")
def testLayoutReturnAll(t, env): """ Return all of a client's layouts FLAGS: pnfs DEPEND: GETLAYOUT1 CODE: LAYOUTRET3 """ # Make sure E_ID returns MDS capabilities c1 = env.c1.new_client(env.testname(t), flags=EXCHGID4_FLAG_USE_PNFS_MDS) if not c1.flags & EXCHGID4_FLAG_USE_PNFS_MDS: fail("Server can not be used as pnfs metadata server") sess = c1.create_session() print sess.c.homedir # Create the file res = create_file(sess, env.testname(t)) check(res) # Get layout fh = res.resarray[-1].object open_stateid = res.resarray[-2].stateid ops = [op.putfh(fh), op.layoutget(False, LAYOUT4_BLOCK_VOLUME, LAYOUTIOMODE4_READ, 0, 0xffffffffffffffff, 0, open_stateid, 0xffff)] res = sess.compound(ops) check(res) # Return layout ops = [op.layoutreturn(False, LAYOUT4_BLOCK_VOLUME, LAYOUTIOMODE4_ANY, layoutreturn4(LAYOUTRETURN4_ALL))] res = sess.compound(ops) check(res)
def testGetDevInfo(t, env): """Check devlist FLAGS: pnfs DEPEND: GETDLIST1 CODE: GETDINFO1 """ # Make sure E_ID returns MDS capabilities c1 = env.c1.new_client(env.testname(t), flags=EXCHGID4_FLAG_USE_PNFS_MDS) if not c1.flags & EXCHGID4_FLAG_USE_PNFS_MDS: fail("Server did not set EXCHGID4_FLAG_USE_PNFS_MDS") sess = c1.create_session() # Test that fs handles block layouts ops = use_obj(env.opts.path) + [op.getattr(1<<FATTR4_FS_LAYOUT_TYPE)] res = sess.compound(ops) check(res) if FATTR4_FS_LAYOUT_TYPE not in res.resarray[-1].obj_attributes: fail("fs_layout_type not available") for lo_type in res.resarray[-1].obj_attributes[FATTR4_FS_LAYOUT_TYPE]: # Send GETDEVICELIST lo_type = LAYOUT4_BLOCK_VOLUME ops = use_obj(env.opts.path) + [op.getdevicelist(lo_type, 0xffffffff, 0, "")] res = sess.compound(ops) check(res) dev_list = res.resarray[-1].gdlr_deviceid_list p = BlockUnpacker("") for dev_id in dev_list: ops = use_obj(env.opts.path) + [op.getdeviceinfo(dev_id, lo_type, 0xffffffff, 0)] res = sess.compound(ops) check(res) if lo_type==LAYOUT4_BLOCK_VOLUME: p.reset(res.resarray[-1].da_addr_body) decode = p.unpack_pnfs_block_deviceaddr4() p.done() print decode
def testReboot(t, env): """Test reboot FLAGS: reboot all CODE: REBOOT1 """ """ cd $HOME echo "test" >foo echo "1" > $ACTIONS/reboot cd $ROOT cd $HOME cat foo """ # cd $HOME os.chdir(env.home) # echo "test" > foo fd = open(env.testname(t), "w") data = "test\n" fd.write(data) fd.close() # echo "1" > $ACTIONS/reboot env.reboot_server() # cd $ROOT os.chdir(env.root) # cd $HOME os.chdir(env.home) # cat foo fd = open(env.testname(t), "r") read = fd.read() fd.close() if read != data: fail("'cat foo' = %r, expected %r" % (read, data))
def testCallbackVersion(t, env): """Check server sends callback program with a version listed in nfs4client.py FLAGS: ganesha CODE: CSESS21 """ cb_occurred = threading.Event() transient = 0x40000000 def mycheck(low, hi, vers): print "Got call using version=%i" % vers cb_occurred.low = low cb_occurred.hi = hi cb_occurred.vers = vers cb_occurred.set() return (low <= vers <= hi) orig = env.c1._check_version try: env.c1._check_version = mycheck c = env.c1.new_client(env.testname(t)) sess = c.create_session(prog=transient) cb_occurred.wait(10) if not cb_occurred.isSet(): fail("No CB_NULL sent") if not (cb_occurred.low <= cb_occurred.vers <= cb_occurred.hi): fail("Expected cb version between %i and %i, got %i" % (cb_occurred.low, cb_occurred.hi, cb_occurred.vers)) finally: env.c1._check_version = orig
def testTwoValueSetupOrCleanup(t, env): """Requires --userparams. Write the MessageType and two values to the OPERATION configuration file on the server. FLAGS: sequence all CODE: TWO_VALUE_SETUP_OR_CLEANUP """ """ cd $HOME echo "Messagetype value value" > $CONFIG/ops/<operation> """ #print 'env.opts.useparams ', env.opts.useparams if len(env.opts.useparams) != 4: print 'TWO_VALUE_SETUP_OR_CLEANUP requires ' print 'testclient.py --useparams' print 'Example: --useparams=sequence:ERROR:NFS4ERR_SEQ_MISORDERED:50 ' print 'which returns NFS4ERR_SEQ_MISORDERED every 50th sequence op' fail("Bad Input to test") operation = env.opts.useparams[0] messagetype = env.opts.useparams[1] value1 = env.opts.useparams[2] value2 = env.opts.useparams[3] # cd $HOME os.chdir(env.home) # Set operation to return error every ceiling times it's processed env.set_two_values(operation, messagetype, value1, value2)
def testSessionReset(t, env): """Test response to server returning NFS4ERR_BADSESSION error on SEQUENCE in OPEN compound FLAGS: sequence all CODE: SESSIONRESET1 """ """ cd $HOME echo "test" >foo echo "NFS4ERR_BADSESSION" > $CONFIG/ops/sequence cd $ROOT cd $HOME cat foo """ # cd $HOME os.chdir(env.home) # echo "test" > foo fd = open(env.testname(t), "w") data = "test\n" fd.write(data) fd.close() # Set sequence to return error env.set_error("sequence", "NFS4ERR_BADSESSION") # cat foo - this compound gets the NFS4ERR_BADSESSION fd = open(env.testname(t), "r") read = fd.read() fd.close() # cd $ROOT - test session recovery for root export os.chdir(env.root) env.clear_two_values("sequence") if read != data: fail("'cat foo' = %r, expected %r" % (read, data))
def testNoUpdate101(t, env): """ FLAGS: exchange_id all CODE: EID5f """ c1 = env.c1.new_client(env.testname(t)) sess1 = c1.create_session() # confirmed==True, verf != old_verf, princ == old_princ # This is case 5 from draft 21 c2 = env.c1.new_client(env.testname(t), verf=env.new_verifier()) if c1.clientid == c2.clientid: fail("Expected clientid %i to change" % c1.clientid) # Old session state should not be discarded until confirm: res = sess1.compound([]) check(res) # Old session state should be discarded after confirm: sess2 = c2.create_session() check(res) res = sess1.compound([]) check(res, NFS4ERR_BADSESSION)
def testCBSecParmsNull(t, env): """Test auth_null callbacks FLAGS: create_session open deleg CODE: DELEG6 """ recall = _testDeleg(t, env, OPEN4_SHARE_ACCESS_READ, OPEN4_SHARE_ACCESS_WANT_READ_DELEG, OPEN4_SHARE_ACCESS_BOTH, sec = [callback_sec_parms4(AUTH_NONE)]) if recall.cred.flavor != AUTH_NONE: fail("expected callback flavor %d, got %d" % (AUTH_NONE, recall.cred.flavor))
def testNoUpdate000(t, env): """ FLAGS: exchange_id all CODE: EID5a """ c1 = env.c1.new_client(env.testname(t), cred=env.cred1) # confirmed==False, verf != old_verf, princ != old_princ # This is an example of case 4 from draft 21 c2 = env.c1.new_client(env.testname(t), verf=env.new_verifier(), cred=env.cred2) if c2.clientid == c1.clientid: fail("Record replacement should create new clientid")
def __create_file_with_deleg(sess, name, access): res = create_file(sess, name, access = access) check(res) fh = res.resarray[-1].object deleg = res.resarray[-2].delegation if (not _got_deleg(deleg)): res = open_file(sess, name, access = access) fh = res.resarray[-1].object deleg = res.resarray[-2].delegation if (not _got_deleg(deleg)): fail("Could not get delegation") return (fh, deleg)
def testNoUpdate111(t, env): """ FLAGS: exchange_id all CODE: EID5h """ c1 = env.c1.new_client(env.testname(t), cred=env.cred1) sess1 = c1.create_session() # confirmed==True, verf == old_verf, princ == old_princ # This is case 2 from draft 21 c2 = env.c1.new_client(env.testname(t), cred=env.cred1) if c1.clientid != c2.clientid: fail("Expected clientid %i, got %i" % (c1.clientid, c2.clientid))
def testUpdate111(t, env): """ FLAGS: exchange_id all CODE: EID6h """ c1 = env.c1.new_client(env.testname(t), cred=env.cred1) sess1 = c1.create_session() # confirmed==True, verf == old_verf, princ == old_princ # This is an example of case 6 from draft-21 c2 = env.c1.new_client(env.testname(t), cred=env.cred1, flags=EXCHGID4_FLAG_UPD_CONFIRMED_REC_A) if c2.clientid != c1.clientid: fail("Record update changed clientid from %r to %r\n" % (c1.clientid, c2.clientid))
def testCsr_sequence(t, env): """The corresponding result of csa_sequence is csr_sequence, which MUST be equal to csa_sequence. FLAGS: create_session all CODE: CSESS24 """ c = env.c1.new_client(env.testname(t)) # CREATE_SESSION chan_attrs = channel_attrs4(0,8192,8192,8192,128,8,[]) csa_sequence = c.seqid sess1 = c.create_session(fore_attrs=chan_attrs) if not nfs4lib.test_equal(sess1.seqid, csa_sequence, "int"): fail("Server returns bad csr_sequence which not equal to csa_sequence")
def testSupported1a(t, env): """Do a simple EXCHANGE_ID - simple flag FLAGS: exchange_id all CODE: EID1a """ c = env.c1 owner = client_owner4(c.verifier, env.testname(t)) protect = state_protect4_a(SP4_NONE) res = c.compound([op.exchange_id(owner, EXCHGID4_FLAG_USE_NON_PNFS, protect, [c.impl_id])]) check(res) # per draft 21 13.1, server MUST set one of these bits if not (res.resarray[0].eir_flags & EXCHGID4_FLAG_MASK_PNFS): fail("server did not set any EXCHGID4_FLAG_USE_* bits")
def testSupported2(t, env): """Do an EXCHANGE_ID from within a session FLAGS: exchange_id all CODE: EID1b """ c1 = env.c1.new_client("%s_1" % env.testname(t)) sess1 = c1.create_session() owner = client_owner4(sess1.c.verifier, "%s_2" % env.testname(t)) protect = state_protect4_a(SP4_NONE) res = sess1.compound([op.exchange_id(owner, EXCHGID4_FLAG_USE_PNFS_DS, protect, [sess1.c.impl_id])]) check(res) # per draft 21 13.1, server MUST set one of these bits if not (res.resarray[0].eir_flags & EXCHGID4_FLAG_MASK_PNFS): fail("server did not set any EXCHGID4_FLAG_USE_* bits")
def testCBSecParms(t, env): """Test auth_sys callbacks FLAGS: create_session open deleg CODE: DELEG5 """ uid = 17 gid = 19 sys_cred = authsys_parms(13, "fake name", uid, gid, []) recall = _testDeleg(t, env, OPEN4_SHARE_ACCESS_READ, OPEN4_SHARE_ACCESS_WANT_READ_DELEG, OPEN4_SHARE_ACCESS_BOTH, sec = [callback_sec_parms4(AUTH_SYS, sys_cred)]) if recall.cred.body.uid != uid or recall.cred.body.gid != gid: fail("expected callback with uid, gid == %d, %d, got %d, %d" % (uid, gid, recall.cred.body.uid, recall.cred.body.gid))
def testSupported2(t, env): """Do an EXCHANGE_ID from within a session FLAGS: exchange_id all CODE: EID1b """ c1 = env.c1.new_client("%s_1" % env.testname(t)) sess1 = c1.create_session() owner = client_owner4(sess1.c.verifier, "%s_2" % env.testname(t)) protect = state_protect4_a(SP4_NONE) res = sess1.compound([op.exchange_id(owner, EXCHGID4_FLAG_USE_PNFS_DS, protect, [sess1.c.impl_id])]) check(res) # per draft 21 13.1, server MUST set one of these bits if not (res.resarray[0].eir_flags & EXCHGID4_FLAG_MASK_PNFS): fail("server did not set any EXCHGID4_FLAG_USE_* bits")
def testReplayCache003(t, env): """Send two unsuccessful idempotent compounds with same seqid FLAGS: sequence all CODE: SEQ9c """ c1 = env.c1.new_client(env.testname(t)) sess1 = c1.create_session() res1 = sess1.compound([op.putrootfh(), op.lookup("")], cache_this=True) check(res1, NFS4ERR_INVAL) res2 = sess1.compound([op.putrootfh(), op.lookup("")], seq_delta=0) check(res2, NFS4ERR_INVAL) res1.tag = res2.tag = "" if not nfs4lib.test_equal(res1, res2): fail("Replay results not equal")
def testReplayCache005(t, env): """Send two unsupported compounds with same seqid FLAGS: sequence all CODE: SEQ9e """ c1 = env.c1.new_client(env.testname(t)) sess1 = c1.create_session() res1 = sess1.compound([op.illegal()], cache_this=True) check(res1, NFS4ERR_OP_ILLEGAL) res2 = sess1.compound([op.illegal()], seq_delta=0) check(res2, NFS4ERR_OP_ILLEGAL) res1.tag = res2.tag = "" if not nfs4lib.test_equal(res1, res2): fail("Replay results not equal")
def testReplayCache006(t, env): """Send two solo sequence compounds with same seqid FLAGS: sequence all CODE: SEQ9f """ c = env.c1.new_client(env.testname(t)) sess = c.create_session() res1 = sess.compound([]) check(res1) res2 = sess.compound([], seq_delta=0) check(res2) res1.tag = res2.tag = "" if not nfs4lib.test_equal(res1, res2): fail("Replay results not equal")
def testReadDeleg(t, env): """Test read delgation handout and return FLAGS: open all CODE: OPEN20 """ recall = threading.Event() def pre_hook(arg, env): recall.stateid = arg.stateid # NOTE this must be done before set() env.notify = recall.set # This is called after compound sent to queue def post_hook(arg, env, res): return res # c1 - OPEN - READ c1 = env.c1.new_client("%s_1" % env.testname(t)) c1.cb_pre_hook(OP_CB_RECALL, pre_hook) c1.cb_post_hook(OP_CB_RECALL, post_hook) sess1 = c1.create_session() res = create_file(sess1, env.testname(t), access=OPEN4_SHARE_ACCESS_READ | OPEN4_SHARE_ACCESS_WANT_READ_DELEG) check(res) fh = res.resarray[-1].object deleg = res.resarray[-2].delegation if deleg.delegation_type == OPEN_DELEGATE_NONE: fail("Could not get delegation") # c2 - OPEN - WRITE c2 = env.c1.new_client("%s_2" % env.testname(t)) sess2 = c2.create_session() claim = open_claim4(CLAIM_NULL, env.testname(t)) owner = open_owner4(0, "My Open Owner 2") how = openflag4(OPEN4_NOCREATE) open_op = op.open(0, OPEN4_SHARE_ACCESS_BOTH, OPEN4_SHARE_DENY_NONE, owner, how, claim) slot = sess2.compound_async(env.home + [open_op]) # Wait for recall, and return delegation recall.wait() # STUB - deal with timeout # Getting here means CB_RECALL reply is in the send queue. # Give it a moment to actually be sent env.sleep(1) res = sess1.compound([op.putfh(fh), op.delegreturn(recall.stateid)]) check(res) # Now get OPEN reply res = sess2.listen(slot) checklist(res, [NFS4_OK, NFS4ERR_DELAY])
def testLayoutCommit(t, env): """ Do some commits FLAGS: pnfs CODE: LAYOUTCOMMIT1 """ sess = env.c1.new_pnfs_client_session(env.testname(t)) blocksize = get_blocksize(sess, use_obj(env.opts.path)) # Create the file res = create_file(sess, env.testname(t)) check(res) # Get layout fh = res.resarray[-1].object open_stateid = res.resarray[-2].stateid ops = [op.putfh(fh), op.layoutget(False, LAYOUT4_BLOCK_VOLUME, LAYOUTIOMODE4_RW, 0, 4*blocksize, 4*blocksize, open_stateid, 0xffff)] res = sess.compound(ops) check(res) layout_stateid = res.resarray[-1].logr_stateid # Parse opaque for layout in res.resarray[-1].logr_layout: if layout.loc_type != LAYOUT4_BLOCK_VOLUME: fail("Did not get Block layout") p = BlockUnpacker(layout.loc_body) opaque = p.unpack_pnfs_block_layout4() p.done() print opaque final_extent = opaque.blo_extents[-1] print final_extent if final_extent.bex_state != PNFS_BLOCK_INVALID_DATA: fail("Expected INVALID_DATA in extent") # LAYOUTCOMMIT final_extent.bex_state = PNFS_BLOCK_READWRITE_DATA p = BlockPacker() p.pack_pnfs_block_layoutupdate4(pnfs_block_layoutupdate4([final_extent])) notime = newtime4(False) ops = [op.putfh(fh), op.layoutcommit(final_extent.bex_file_offset, final_extent.bex_length, False, layout_stateid, newoffset4(True, 4 * blocksize - 1), notime, layoutupdate4(LAYOUT4_BLOCK_VOLUME, p.get_buffer()))] res = sess.compound(ops) check(res) print res
def testDestroy2(t, env): """ - create client (exchangeid) - create session - destroy session - create a new session for the same client - do something that triggers a callback (look at the delegation tests for example) - check that we get the callback FLAGS: destroy_session CODE: DSESS9002 """ recall = threading.Event() def pre_hook(arg, env): recall.stateid = arg.stateid # NOTE this must be done before set() recall.happened = True env.notify = recall.set # This is called after compound sent to queue def post_hook(arg, env, res): return res c = env.c1.new_client(env.testname(t)) sess1 = c.create_session() sess1.compound([op.reclaim_complete(FALSE)]) res = c.c.compound([op.destroy_session(sess1.sessionid)]) sess2 = c.create_session() res = create_file(sess2, env.testname(t), access=OPEN4_SHARE_ACCESS_READ | OPEN4_SHARE_ACCESS_WANT_READ_DELEG) check(res) fh = res.resarray[-1].object deleg = res.resarray[-2].delegation if deleg.delegation_type == OPEN_DELEGATE_NONE: fail("Could not get delegation") c2 = env.c1.new_client("%s_2" % env.testname(t)) sess3 = c2.create_session() sess3.compound([op.reclaim_complete(FALSE)]) claim = open_claim4(CLAIM_NULL, env.testname(t)) owner = open_owner4(0, "My Open Owner 2") how = openflag4(OPEN4_NOCREATE) open_op = op.open(0, OPEN4_SHARE_ACCESS_BOTH, OPEN4_SHARE_DENY_NONE, owner, how, claim) c.cb_pre_hook(OP_CB_RECALL, pre_hook) c.cb_post_hook(OP_CB_RECALL, post_hook) slot = sess3.compound_async(env.home + [open_op]) recall.happened = False recall.wait(100) # STUB - deal with timeout if not recall.happened: fail("Did not get callback")
def testReplayCache004(t, env): """Send two unsuccessful non-idempotent compounds with same seqid FLAGS: sequence all CODE: SEQ9d """ c1 = env.c1.new_client(env.testname(t)) sess1 = c1.create_session() ops = [op.putrootfh(), op.savefh(), op.rename("", "foo")] res1 = sess1.compound(ops, cache_this=True) check(res1, NFS4ERR_INVAL) res2 = sess1.compound(ops, seq_delta=0) check(res2, NFS4ERR_INVAL) res1.tag = res2.tag = "" if not nfs4lib.test_equal(res1, res2): fail("Replay results not equal")
def testUpdate111(t, env): """ FLAGS: exchange_id all CODE: EID6h """ c1 = env.c1.new_client(env.testname(t), cred=env.cred1) sess1 = c1.create_session() # confirmed==True, verf == old_verf, princ == old_princ # This is an example of case 6 from draft-21 c2 = env.c1.new_client(env.testname(t), cred=env.cred1, flags=EXCHGID4_FLAG_UPD_CONFIRMED_REC_A) if c2.clientid != c1.clientid: fail("Record update changed clientid from %r to %r\n" % (c1.clientid, c2.clientid))
def testSupported1a(t, env): """Do a simple EXCHANGE_ID - simple flag FLAGS: exchange_id all CODE: EID1a """ c = env.c1 owner = client_owner4(c.verifier, env.testname(t)) protect = state_protect4_a(SP4_NONE) res = c.compound([ op.exchange_id(owner, EXCHGID4_FLAG_USE_NON_PNFS, protect, [c.impl_id]) ]) check(res) # per draft 21 13.1, server MUST set one of these bits if not (res.resarray[0].eir_flags & EXCHGID4_FLAG_MASK_PNFS): fail("server did not set any EXCHGID4_FLAG_USE_* bits")
def testNoUpdate110(t, env): """ FLAGS: exchange_id all CODE: EID5g """ c1 = env.c1.new_client(env.testname(t), cred=env.cred1) sess1 = c1.create_session() # confirmed==True, verf == old_verf, princ != old_princ # This is an example of case 3 from draft 21 c2 = env.c1.new_client(env.testname(t), cred=env.cred2) if c2.clientid == c1.clientid: fail("Record replacement should create new clientid") # Check that cred1 state is destroyed res = sess1.compound([]) check(res, NFS4ERR_BADSESSION)
def testReplay1(t, env): """Replay a successful CREATE_SESSION FLAGS: create_session all CODE: CSESS5 """ c = env.c1.new_client(env.testname(t)) # CREATE_SESSION res1 = create_session(c.c, c.clientid, c.seqid) check(res1) # REPLAY res2 = create_session(c.c, c.clientid, c.seqid) check(res2) # Test results are equal (ignoring tags) res1.tag = res2.tag = "" if not nfs4lib.test_equal(res1, res2): fail("Replay results not equal")
def testNoUpdate110(t, env): """ FLAGS: exchange_id all CODE: EID5g """ c1 = env.c1.new_client(env.testname(t), cred=env.cred1) sess1 = c1.create_session() # confirmed==True, verf == old_verf, princ != old_princ # This is an example of case 3 from draft 21 c2 = env.c1.new_client(env.testname(t), cred=env.cred2) if c2.clientid == c1.clientid: fail("Record replacement should create new clientid") # Check that cred1 state is destroyed res = sess1.compound([]) check(res, NFS4ERR_BADSESSION)
def testStateid1(t, env): """Check for proper sequence handling in layout stateids. FLAGS: block CODE: BLOCK1 """ sess = env.c1.new_client_session(env.testname(t), flags=EXCHGID4_FLAG_USE_PNFS_MDS) # Create the file res = create_file(sess, env.testname(t)) check(res) # Get layout 1 fh = res.resarray[-1].object open_stateid = res.resarray[-2].stateid print open_stateid ops = [ op.putfh(fh), op.layoutget(False, LAYOUT4_BLOCK_VOLUME, LAYOUTIOMODE4_RW, 0, 8192, 8192, open_stateid, 0xffff) ] res = sess.compound(ops) check(res) lo_stateid = res.resarray[-1].logr_stateid print lo_stateid if lo_stateid.seqid != 1: # From draft23 12.5.2 "The first successful LAYOUTGET processed by # the server using a non-layout stateid as an argument MUST have the # "seqid" field of the layout stateid in the response set to one." fail("Expected stateid.seqid==1, got %i" % lo_stateid.seqid) for i in range(6): # Get subsequent layouts ops = [ op.putfh(fh), op.layoutget(False, LAYOUT4_BLOCK_VOLUME, LAYOUTIOMODE4_RW, (i + 1) * 8192, 8192, 8192, lo_stateid, 0xffff) ] res = sess.compound(ops) check(res) lo_stateid = res.resarray[-1].logr_stateid print lo_stateid if lo_stateid.seqid != i + 2: # From draft23 12.5.3 "After the layout stateid is established, # the server increments by one the value of the "seqid" in each # subsequent LAYOUTGET and LAYOUTRETURN response, fail("Expected stateid.seqid==%i, got %i" % (i + 2, lo_stateid.seqid))
def testReplay2(t, env): """Replay a unsuccessful CREATE_SESSION FLAGS: create_session all DEPEND: CSESS9 CODE: CSESS6 """ c = env.c1.new_client(env.testname(t), cred=env.cred1) res1 = create_session(c.c, c.clientid, c.seqid, cred=env.cred2) check(res1, NFS4ERR_CLID_INUSE) # REPLAY res2 = create_session(c.c, c.clientid, c.seqid, cred=env.cred2) check(res2, NFS4ERR_CLID_INUSE) # Test results are equal (ignoring tags) res1.tag = res2.tag = "" if not nfs4lib.test_equal(res1, res2): fail("Replay results not equal")
def testReplay1(t, env): """Replay a successful CREATE_SESSION FLAGS: create_session all CODE: CSESS5 """ c = env.c1.new_client(env.testname(t)) # CREATE_SESSION res1 = create_session(c.c, c.clientid, c.seqid) check(res1) # REPLAY res2 = create_session(c.c, c.clientid, c.seqid) check(res2) # Test results are equal (ignoring tags) res1.tag = res2.tag = "" if not nfs4lib.test_equal(res1, res2): fail("Replay results not equal")
def testDestroy2(t, env): """ - create client (exchangeid) - create session - destroy session - create a new session for the same client - do something that triggers a callback (look at the delegation tests for example) - check that we get the callback FLAGS: destroy_session CODE: DSESS9002 """ recall = threading.Event() def pre_hook(arg, env): recall.stateid = arg.stateid # NOTE this must be done before set() recall.happened = True env.notify = recall.set # This is called after compound sent to queue def post_hook(arg, env, res): return res c = env.c1.new_client(env.testname(t)) sess1 = c.create_session() res = c.c.compound([op.destroy_session(sess1.sessionid)]) sess2 = c.create_session() res = create_file(sess2, env.testname(t), access=OPEN4_SHARE_ACCESS_READ | OPEN4_SHARE_ACCESS_WANT_READ_DELEG) check(res) fh = res.resarray[-1].object deleg = res.resarray[-2].delegation if deleg.delegation_type == OPEN_DELEGATE_NONE: fail("Could not get delegation") c2 = env.c1.new_client("%s_2" % env.testname(t)) sess3 = c2.create_session() claim = open_claim4(CLAIM_NULL, env.testname(t)) owner = open_owner4(0, "My Open Owner 2") how = openflag4(OPEN4_NOCREATE) open_op = op.open(0, OPEN4_SHARE_ACCESS_BOTH, OPEN4_SHARE_DENY_NONE, owner, how, claim) c.cb_pre_hook(OP_CB_RECALL, pre_hook) c.cb_post_hook(OP_CB_RECALL, post_hook) slot = sess3.compound_async(env.home + [open_op]) recall.happened = False recall.wait(100) # STUB - deal with timeout if not recall.happened: fail("Did not get callback")
def testReplayCache002(t, env): """Send two successful non-idempotent compounds with same seqid FLAGS: sequence all CODE: SEQ9b """ sess1 = env.c1.new_client_session(env.testname(t)) res = create_file(sess1, "%s_1" % env.testname(t)) check(res) ops = env.home + [op.savefh(),\ op.rename("%s_1" % env.testname(t), "%s_2" % env.testname(t))] res1 = sess1.compound(ops, cache_this=True) check(res1) res2 = sess1.compound(ops, seq_delta=0) check(res2) res1.tag = res2.tag = "" if not nfs4lib.test_equal(res1, res2): fail("Replay results not equal")
def testCBSecParms(t, env): """Test auth_sys callbacks FLAGS: create_session open deleg CODE: DELEG5 """ uid = 17 gid = 19 sys_cred = authsys_parms(13, "fake name", uid, gid, []) recall = _testDeleg(t, env, OPEN4_SHARE_ACCESS_READ, OPEN4_SHARE_ACCESS_WANT_READ_DELEG, OPEN4_SHARE_ACCESS_BOTH, sec=[callback_sec_parms4(AUTH_SYS, sys_cred)]) if recall.cred.body.uid != uid or recall.cred.body.gid != gid: fail("expected callback with uid, gid == %d, %d, got %d, %d" % (uid, gid, recall.cred.body.uid, recall.cred.body.gid))
def testMaxreqs(t, env): """A CREATE_SESSION with maxreqs too large should return a modified value FLAGS: create_session all CODE: CSESS22 """ # Assuming this is too large for any server; increase if necessary: # but too huge will eat many memory for replay_cache, be careful! TOO_MANY_SLOTS = 500 c = env.c1.new_client(env.testname(t)) # CREATE_SESSION with fore_channel = TOO_MANY_SLOTS chan_attrs = channel_attrs4(0,8192,8192,8192,128, TOO_MANY_SLOTS, []) sess1 = c.create_session(fore_attrs=chan_attrs) if nfs4lib.test_equal(sess1.fore_channel.maxrequests, chan_attrs.ca_maxrequests, "count4"): fail("Server allows surprisingly large fore_channel maxreqs")
def testNoUpdate100(t, env): """ FLAGS: exchange_id all CODE: EID5e """ c1 = env.c1.new_client(env.testname(t), cred=env.cred1) sess1 = c1.create_session() res = c1.c.compound([op.destroy_session(sess1.sessionid)]) check(res) # confirmed==True, verf != old_verf, princ != old_princ, no state # This is an example of case 3 from draft 21 c2 = env.c1.new_client(env.testname(t), cred=env.cred2, verf=env.new_verifier()) if c2.clientid == c1.clientid: fail("Record replacement should create new clientid") # Check that cred1 state is destroyed res = c1._create_session() check(res, NFS4ERR_STALE_CLIENTID)
def testNoUpdate101(t, env): """ FLAGS: exchange_id all CODE: EID5f """ c1 = env.c1.new_client(env.testname(t)) sess1 = c1.create_session() # confirmed==True, verf != old_verf, princ == old_princ # This is case 5 from draft 21 c2 = env.c1.new_client(env.testname(t), verf=env.new_verifier()) if c1.clientid == c2.clientid: fail("Expected clientid %i to change" % c1.clientid) # Old session state should not be discarded until confirm: res = sess1.compound([]) check(res)
def testReboot2(t, env): """Test v4.1 reboot with no state operation FLAGS: reboot all CODE: REBOOT2 """ """ cd $HOME mkdir testdir cd testdir mkdir datadir - so that listdir(testdir) only has datadir echo "1" > $ACTIONS/reboot cd $ROOT - kick off session recovery for root cd $HOME - kick off session recovery for home cd testdir listdir(testdir) """ # cd $HOME os.chdir(env.home) # make a directory to hold the single datadir directory testdir = env.testname(t) os.mkdir(testdir) # cd testsdir os.chdir(testdir) # make a directory datadir = "testit" os.mkdir(datadir) # echo "test" > foo # echo "1" > $ACTIONS/reboot env.reboot_server() # cd $ROOT os.chdir(env.root) # cd $HOME os.chdir(env.home) # read the directory read = os.listdir(testdir) # cleanup os.chdir(testdir) os.rmdir(datadir) os.chdir(env.home) os.rmdir(testdir) if read[0] != datadir: fail("'listdir foo' = %r, expected %r" % (read, data))
def testGetDevList(t, env): """Check devlist FLAGS: layout all CODE: LAYOUT2 """ sess = env.c1.new_pnfs_client_session(env.testname(t)) # Test that fs handles block layouts ops = use_obj(env.opts.path) + [op.getattr(1 << FATTR4_FS_LAYOUT_TYPES)] res = sess.compound(ops) check(res) if FATTR4_FS_LAYOUT_TYPES not in res.resarray[-1].obj_attributes: fail("fs_layout_type not available") if LAYOUT4_BLOCK_VOLUME not in res.resarray[-1].obj_attributes[ FATTR4_FS_LAYOUT_TYPES]: fail("layout_type does not contain BLOCK") # Send GETDEVICELIST ops = use_obj( env.opts.path) + [op.getdevicelist(LAYOUT4_BLOCK_VOLUME, 0, 0, "")] res = sess.compound(ops) check(res)
def testOPENClaimFH(t, env): """OPEN file with claim_type is CLAIM_FH FLAGS: open all CODE: OPEN7 """ sess1 = env.c1.new_client_session(env.testname(t)) res = create_file(sess1, env.testname(t), want_deleg=False) check(res) fh = res.resarray[-1].object stateid = res.resarray[-2].stateid res = close_file(sess1, fh, stateid=stateid) check(res) claim = open_claim4(CLAIM_FH) how = openflag4(OPEN4_NOCREATE) oowner = open_owner4(0, "My Open Owner 2") access = OPEN4_SHARE_ACCESS_BOTH | OPEN4_SHARE_ACCESS_WANT_NO_DELEG open_op = op.open(0, access, OPEN4_SHARE_DENY_NONE, oowner, how, claim) res = sess1.compound([op.putfh(fh), open_op]) check(res) stateid = res.resarray[-1].stateid stateid.seqid = 0 data = "write test data" res = sess1.compound( [op.putfh(fh), op.write(stateid, 5, FILE_SYNC4, data)]) check(res) res = sess1.compound([op.putfh(fh), op.read(stateid, 0, 1000)]) check(res) if not res.resarray[-1].eof: fail("EOF not set on read") desired = "\0" * 5 + data if res.resarray[-1].data != desired: fail("Expected %r, got %r" % (desired, res.resarray[-1].data)) res = close_file(sess1, fh, stateid=stateid) check(res)
def testGetDevList(t, env): """Check devlist FLAGS: layout all CODE: LAYOUT2 """ # Make sure E_ID returns MDS capabilities c1 = env.c1.new_client(env.testname(t), flags=EXCHGID4_FLAG_USE_PNFS_MDS) if not c1.flags & EXCHGID4_FLAG_USE_PNFS_MDS: fail("Server can not be used as pnfs metadata server") sess = c1.create_session() # Test that fs handles block layouts ops = use_obj(env.opts.path) + [op.getattr(1 << FATTR4_FS_LAYOUT_TYPE)] res = sess.compound(ops) check(res) if FATTR4_FS_LAYOUT_TYPE not in res.resarray[-1].obj_attributes: fail("fs_layout_type not available") if LAYOUT4_BLOCK_VOLUME not in res.resarray[-1].obj_attributes[ FATTR4_FS_LAYOUT_TYPE]: fail("layout_type does not contain BLOCK") # Send GETDEVICELIST ops = use_obj( env.opts.path) + [op.getdevicelist(LAYOUT4_BLOCK_VOLUME, 0, 0, "")] res = sess.compound(ops) check(res)
def testLayout(t, env): """Verify layout handling FLAGS: layout all CODE: LAYOUT1 """ # Make sure E_ID returns MDS capabilities c1 = env.c1.new_client(env.testname(t), flags=EXCHGID4_FLAG_USE_PNFS_MDS) if not c1.flags & EXCHGID4_FLAG_USE_PNFS_MDS: fail("Server can not be used as pnfs metadata server") sess = c1.create_session() # Test that fs handles block layouts ops = use_obj(env.opts.path) + [op.getattr(1<<FATTR4_FS_LAYOUT_TYPE)] res = sess.compound(ops) check(res) if FATTR4_FS_LAYOUT_TYPE not in res.resarray[-1].obj_attributes: fail("fs_layout_type not available") if LAYOUT4_BLOCK_VOLUME not in res.resarray[-1].obj_attributes[FATTR4_FS_LAYOUT_TYPE]: fail("layout_type does not contain BLOCK") # Open the file owner = "owner for %s" % env.testname(t) # openres = open_file(sess, owner, env.opts.path + ["simple_extent"]) openres = open_file(sess, owner, env.opts.path + ["hole_between_extents"]) check(openres) # Get a layout fh = openres.resarray[-1].object ops = [op.putfh(fh), op.layoutget(False, LAYOUT4_BLOCK_VOLUME, LAYOUTIOMODE4_READ, 0, 0xffffffff, 0, 0xffff)] res = sess.compound(ops) check(res)
def testCBSecParmsChange(t, env): """Test changing of auth_sys callbacks with backchannel_ctl FLAGS: create_session open deleg backchannel_ctl CODE: DELEG7 """ uid1 = 17 gid1 = 19 sys_cred1 = cbsp_sy_cred = authsys_parms(13, "fake name", uid1, gid1, []) uid2 = 29 gid2 = 31 sys_cred2 = cbsp_sy_cred = authsys_parms(13, "fake name", uid2, gid2, []) recall = _testDeleg(t, env, OPEN4_SHARE_ACCESS_READ, OPEN4_SHARE_ACCESS_WANT_READ_DELEG, OPEN4_SHARE_ACCESS_BOTH, sec=[callback_sec_parms4(AUTH_SYS, sys_cred1)], sec2=[callback_sec_parms4(AUTH_SYS, sys_cred2)]) if recall.cred.body.uid != uid2 or recall.cred.body.gid != gid2: fail("expected callback with uid, gid == %d, %d, got %d, %d" % (uid2, gid2, recall.cred.body.uid, recall.cred.body.gid))
def testGetDevInfo(t, env): """Check devlist FLAGS: getdevicelist all DEPEND: GETDLIST1 CODE: GETDINFO1 """ # Make sure E_ID returns MDS capabilities c1 = env.c1.new_client(env.testname(t), flags=EXCHGID4_FLAG_USE_PNFS_MDS) if not c1.flags & EXCHGID4_FLAG_USE_PNFS_MDS: fail("Server did not set EXCHGID4_FLAG_USE_PNFS_MDS") sess = c1.create_session() # Test that fs handles block layouts ops = use_obj(env.opts.path) + [op.getattr(1 << FATTR4_FS_LAYOUT_TYPE)] res = sess.compound(ops) check(res) if FATTR4_FS_LAYOUT_TYPE not in res.resarray[-1].obj_attributes: fail("fs_layout_type not available") for lo_type in res.resarray[-1].obj_attributes[FATTR4_FS_LAYOUT_TYPE]: # Send GETDEVICELIST lo_type = LAYOUT4_BLOCK_VOLUME ops = use_obj( env.opts.path) + [op.getdevicelist(lo_type, 0xffffffff, 0, "")] res = sess.compound(ops) check(res) dev_list = res.resarray[-1].gdlr_deviceid_list p = BlockUnpacker("") for dev_id in dev_list: ops = use_obj(env.opts.path) + [ op.getdeviceinfo(dev_id, lo_type, 0xffffffff, 0) ] res = sess.compound(ops) check(res) if lo_type == LAYOUT4_BLOCK_VOLUME: p.reset(res.resarray[-1].da_addr_body) decode = p.unpack_pnfs_block_deviceaddr4() p.done() print decode
def testLayoutReturnFile(t, env): """ Return a file's layout FLAGS: layoutreturn all DEPEND: GETLAYOUT1 CODE: LAYOUTRET1 """ # Make sure E_ID returns MDS capabilities c1 = env.c1.new_client(env.testname(t), flags=EXCHGID4_FLAG_USE_PNFS_MDS) if not c1.flags & EXCHGID4_FLAG_USE_PNFS_MDS: fail("Server can not be used as pnfs metadata server") sess = c1.create_session() # Create the file res = create_file(sess, env.testname(t)) check(res) # Get layout fh = res.resarray[-1].object open_stateid = res.resarray[-2].stateid ops = [ op.putfh(fh), op.layoutget(False, LAYOUT4_BLOCK_VOLUME, LAYOUTIOMODE4_READ, 0, 0xffffffffffffffff, 0, open_stateid, 0xffff) ] res = sess.compound(ops) check(res) # Return layout layout_stateid = res.resarray[-1].logr_stateid ops = [ op.putfh(fh), op.layoutreturn( False, LAYOUT4_BLOCK_VOLUME, LAYOUTIOMODE4_ANY, layoutreturn4( LAYOUTRETURN4_FILE, layoutreturn_file4(0, 0xffffffffffffffff, layout_stateid, ""))) ] res = sess.compound(ops) check(res)
def testReplay1b(t, env): """Replay a successful SEQUENCE:CREATE_SESSION without a preceeding SEQUENCE FLAGS: create_session all CODE: CSESS5b """ c = env.c1.new_client(env.testname(t)) # CREATE_SESSION sess1 = c.create_session() # another CREATE_SESSION with SEQUENCE from first session c.seqid = 2 chan_attrs = channel_attrs4(0,8192,8192,8192,128,8,[]) cs_op = op.create_session(c.clientid, c.seqid, 0, chan_attrs, chan_attrs, c.c.prog, []) res1 = sess1.compound([cs_op]) check(res1) # REPLAY second CREATE_SESSION without SEQUENCE res2 = create_session(c.c, c.clientid, c.seqid) check(res2) # Test results are equal (ignoring tags) res1.tag = res2.tag = "" if not nfs4lib.test_equal(res1, res2): fail("Replay results not equal")
def testDestroy3(t, env): """ - create client (exchangeid) - create session - trigger callback; check that it arrives, but don't answer it. - destroy session - create new session - check that a new callback is sent over the new session. Some servers will do this very quickly, some might take longer. FLAGS: destroy_session CODE: DSESS9003 """ recall = threading.Event() def pre_hook(arg, env): recall.stateid = arg.stateid # NOTE this must be done before set() recall.happened = True env.notify = recall.set # This is called after compound sent to queue def bad_post_hook(arg, env, res): return None; def good_post_hook(arg, env, res): return res c = env.c1.new_client(env.testname(t)) sess1 = c.create_session() res = create_file(sess1, env.testname(t), access=OPEN4_SHARE_ACCESS_READ | OPEN4_SHARE_ACCESS_WANT_READ_DELEG) check(res) fh = res.resarray[-1].object deleg = res.resarray[-2].delegation print "OPEN fh =", repr(fh) if deleg.delegation_type == OPEN_DELEGATE_NONE: fail("Could not get delegation") recall.happened = False c2 = env.c1.new_client("%s_2" % env.testname(t)) sess2 = c2.create_session() claim = open_claim4(CLAIM_NULL, env.testname(t)) owner = open_owner4(0, "My Open Owner 2") how = openflag4(OPEN4_NOCREATE) open_op = op.open(0, OPEN4_SHARE_ACCESS_BOTH, OPEN4_SHARE_DENY_NONE, owner, how, claim) slot = sess2.compound_async(env.home + [open_op]) c.cb_pre_hook(OP_CB_RECALL, pre_hook) c.cb_post_hook(OP_CB_RECALL, bad_post_hook) recall.wait(1) # STUB - deal with timeout if not recall.happened: fail("Did not get callback") recall.happened = False # since we did not reply to callback, robust server should retry when # we give it a new backchannel to use: res = c.c.compound([op.destroy_session(sess1.sessionid)]) c.cb_pre_hook(OP_CB_RECALL, pre_hook) c.cb_post_hook(OP_CB_RECALL, good_post_hook) sess3 = c.create_session() recall.wait(100) # STUB - deal with timeout if not recall.happened: fail("Did not get callback")
def testReadWrite(t, env): """Do a simple READ and WRITE FLAGS: open all CODE: OPEN30 """ sess1 = env.c1.new_client_session(env.testname(t)) owner = open_owner4(0, "My Open Owner") res = create_file(sess1, env.testname(t)) check(res) expect(res, seqid=1) fh = res.resarray[-1].object stateid = res.resarray[-2].stateid stateid.seqid = 0 data = "write test data" res = sess1.compound([op.putfh(fh), op.write(stateid, 5, FILE_SYNC4, data)]) check(res) res = sess1.compound([op.putfh(fh), op.read(stateid, 0, 1000)]) check(res) if not res.resarray[-1].eof: fail("EOF not set on read") desired = "\0"*5 + data if res.resarray[-1].data != desired: fail("Expected %r, got %r" % (desired, res.resarray[-1].data))
def testReplay1a(t, env): """Replay a successful CREATE_SESSION with a SEQUENCE from a different session FLAGS: create_session all CODE: CSESS5a """ c = env.c1.new_client(env.testname(t)) # CREATE_SESSION sess1 = c.create_session() # another CREATE_SESSION c.seqid = 2 chan_attrs = channel_attrs4(0,8192,8192,8192,128,8,[]) sec = [callback_sec_parms4(0)] res1 = create_session(c.c, c.clientid, c.seqid) check(res1) # REPLAY first CREATE_SESSION with SEQUENCE from 2nd session cs_op = op.create_session(c.clientid, c.seqid, 0, chan_attrs, chan_attrs, c.c.prog, sec) res2 = sess1.compound([cs_op]) check(res2) # Test results are equal (ignoring tags) res1.tag = res2.tag = "" if not nfs4lib.test_equal(res1, res2): fail("Replay results not equal")
def testDelegRevocation(t, env): """Allow a delegation to be revoked, check that TEST_STATEID and FREE_STATEID have the required effect. FLAGS: deleg CODE: DELEG8 """ sess1 = env.c1.new_client_session("%s_1" % env.testname(t)) fh, deleg = __create_file_with_deleg( sess1, env.testname(t), OPEN4_SHARE_ACCESS_READ | OPEN4_SHARE_ACCESS_WANT_READ_DELEG) delegstateid = deleg.read.stateid sess2 = env.c1.new_client_session("%s_2" % env.testname(t)) claim = open_claim4(CLAIM_NULL, env.testname(t)) owner = open_owner4(0, "My Open Owner 2") how = openflag4(OPEN4_NOCREATE) open_op = op.open(0, OPEN4_SHARE_ACCESS_WRITE, OPEN4_SHARE_DENY_NONE, owner, how, claim) while 1: res = sess2.compound(env.home + [open_op]) if res.status == NFS4_OK: break check(res, [NFS4_OK, NFS4ERR_DELAY]) # just to keep sess1 renewed. This is a bit fragile, as we # depend on the above compound waiting no longer than the # server's lease period: res = sess1.compound([]) res = sess1.compound([op.putfh(fh), op.read(delegstateid, 0, 1000)]) check(res, NFS4ERR_DELEG_REVOKED, "Read with a revoked delegation") slot, seq_op = sess1._prepare_compound({}) res = sess1.c.compound([seq_op]) flags = res.resarray[0].sr_status_flags if not (flags & SEQ4_STATUS_RECALLABLE_STATE_REVOKED): fail("SEQ4_STATUS_RECALLABLE_STATE_REVOKED should be set after" " sucess of open conflicting with delegation") flags &= ~SEQ4_STATUS_RECALLABLE_STATE_REVOKED if flags: print("WARNING: unexpected status flag(s) 0x%x set" % flags) res = sess1.update_seq_state(res, slot) res = sess1.compound([op.test_stateid([delegstateid])]) stateid_stat = res.resarray[0].tsr_status_codes[0] if stateid_stat != NFS4ERR_DELEG_REVOKED: fail("TEST_STATEID on revoked stateid should report status" " NFS4ERR_DELEG_REVOKED, instead got %s" % nfsstat4[stateid_stat]) res = sess1.compound([op.free_stateid(delegstateid)]) check(res) slot, seq_op = sess1._prepare_compound({}) res = sess1.c.compound([seq_op]) flags = res.resarray[0].sr_status_flags if flags & SEQ4_STATUS_RECALLABLE_STATE_REVOKED: fail("SEQ4_STATUS_RECALLABLE_STATE_REVOKED should be cleared after" " FREE_STATEID") if flags & ~SEQ4_STATUS_RECALLABLE_STATE_REVOKED: print("WARNING: unexpected status flag(s) 0x%x set" % flags)
def testEMCGetLayout(t, env): """Verify layout handling Debugging test that looks for pre-existing file (server2fs1/dump.eth) so we don't have to worry about creating a file. FLAGS: CODE: GETLAYOUT100 """ # Make sure E_ID returns MDS capabilities c1 = env.c1.new_client(env.testname(t), flags=EXCHGID4_FLAG_USE_PNFS_MDS) if not c1.flags & EXCHGID4_FLAG_USE_PNFS_MDS: fail("Server can not be used as pnfs metadata server") sess = c1.create_session() # Test that fs handles block layouts ops = use_obj(env.opts.path) + [op.getattr(1 << FATTR4_FS_LAYOUT_TYPE)] res = sess.compound(ops) check(res) if FATTR4_FS_LAYOUT_TYPE not in res.resarray[-1].obj_attributes: fail("fs_layout_type not available") if LAYOUT4_BLOCK_VOLUME not in res.resarray[-1].obj_attributes[ FATTR4_FS_LAYOUT_TYPE]: fail("layout_type does not contain BLOCK") # Create the file file = ["server2fs1", "dump.eth"] res = open_file(sess, env.testname(t), file) check(res) # Get layout fh = res.resarray[-1].object stateid = res.resarray[-2].stateid stateid.seqid = 0 ops = [ op.putfh(fh), op.layoutget(False, LAYOUT4_BLOCK_VOLUME, LAYOUTIOMODE4_READ, 0, 0xffffffffffffffff, 0, stateid, 0xffff) ] res = sess.compound(ops) check(res) # Parse opaque for layout in res.resarray[-1].logr_layout: if layout.loc_type == LAYOUT4_BLOCK_VOLUME: p = BlockUnpacker(layout.loc_body) opaque = p.unpack_pnfs_block_layout4() p.done() print opaque
def testNoDeleg(t, env): """Test no delegation handout FLAGS: open deleg CODE: DELEG4 """ sess1 = env.c1.new_client_session("%s_1" % env.testname(t)) res = create_file(sess1, env.testname(t), access=OPEN4_SHARE_ACCESS_READ | OPEN4_SHARE_ACCESS_WANT_NO_DELEG) check(res) fh = res.resarray[-1].object deleg = res.resarray[-2].delegation if deleg.delegation_type == OPEN_DELEGATE_NONE: fail("Got no delegation, expected OPEN_DELEGATE_NONE_EXT") if deleg.delegation_type != OPEN_DELEGATE_NONE_EXT: fail("Got a delegation (type " + str(deleg.delegation_type) + ") despite asking for none") if deleg.ond_why != WND4_NOT_WANTED: fail("Wrong reason (" + str(deleg.ond_why) + ") for giving no delegation")