def shutDown(self): """Run after each test""" log.debug("post-test") client_index = 0 clients = {} for sessid in self.c1.sessions: session = self.c1.sessions[sessid] if session is None: continue clients[client_index] = session.client client_index += 1 res = self.c1.compound([op.destroy_session(sessid)]) if res.status != NFS4_OK: log.info("Could not clean up session: status %s" % nfsstat4[res.status]) session.client._del_session(session) for client_index in clients: client = clients[client_index] if client == self.c1: continue res = self.c1.compound([op.destroy_clientid(client.clientid)]) if res.status != NFS4_OK: log.info("Could not clean up client: status %s" % nfsstat4[res.status]) log.debug("done post-test")
def testDestoryNotSoleOps(t, env): """ If the COMPOUND request does not start with SEQUENCE, and DESTROY_SESSION is not the sole operation, then server MUST return NFS4ERR_NOT_ONLY_OP. rfc5661 18.37.3 FLAGS: destroy_session CODE: DSESS9005 """ c = env.c1.new_client(env.testname(t)) sess1 = c.create_session() sid = sess1.sessionid res = c.c.compound([op.destroy_session(sess1.sessionid), op.putrootfh()]) check(res, NFS4ERR_NOT_ONLY_OP) res = c.c.compound([op.putrootfh(), op.destroy_session(sess1.sessionid)]) check(res, NFS4ERR_NOT_ONLY_OP)
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 testDestroy(t, env): """ - create a session - create a new tcp connection - Send a DESTROY_SESSION over the new tcp connection. It should fail with nfserr_conn_not_bound_to_session. - Send a SEQUENCE over the new tcp connection. - Send a DESTROY_SESSION over the new tcp connection. - This time it should succeed. FLAGS: destroy_session CODE: DSESS9001 """ c = env.c1.new_client(env.testname(t)) sess = c.create_session() rogue = env.c1.connect(env.c1.server_address) res = c.c.compound([op.destroy_session(sess.sessionid)], pipe=rogue) check(res, NFS4ERR_CONN_NOT_BOUND_TO_SESSION) env.c1.compound([sess.seq_op()], pipe=rogue) res = c.c.compound([op.destroy_session(sess.sessionid)], pipe=rogue) check(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() 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 testDestoryNotFinalOps(t, env): """ If the COMPOUND request starts with SEQUENCE, DESTROY_SESSION MUST be the final operation in the COMPOUND request. rfc5661 18.37.3 FLAGS: destroy_session CODE: DSESS9004 """ c = env.c1.new_client(env.testname(t)) sess1 = c.create_session() sid = sess1.sessionid res = c.c.compound([op.sequence(sid, 1, 2, 3, False), op.destroy_session(sess1.sessionid), op.putrootfh()]) check(res, NFS4ERR_NOT_ONLY_OP)
def testUseTwoSessions(t, env): """Use multiple sessions per client FLAGS: trunking all CODE: TRUNK2 """ c = env.c1.new_client(env.testname(t)) sess = c.create_session() res = sess.compound([]) check(res) sess2 = c.create_session() res = sess2.compound([]) check(res) res = c.c.compound([op.destroy_session(sess.sessionid)]) check(res) res = sess2.compound([]) check(res)
def testDestoryNotFinalOps(t, env): """ If the COMPOUND request starts with SEQUENCE, DESTROY_SESSION MUST be the final operation in the COMPOUND request. rfc5661 18.37.3 FLAGS: destroy_session CODE: DSESS9004 """ c = env.c1.new_client(env.testname(t)) sess1 = c.create_session() sid = sess1.sessionid res = c.c.compound([ op.sequence(sid, 1, 2, 3, False), op.destroy_session(sess1.sessionid), op.putrootfh() ]) check(res, NFS4ERR_NOT_ONLY_OP)
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() res = c1.c.compound([op.destroy_session(sess1.sessionid)]) check(res) # 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 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")