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 testReadWrite(t, env): """Do a simple READ and WRITE FLAGS: open all CODE: OPEN400 """ c1 = env.c1.new_client(env.testname(t)) sess1 = c1.create_session() owner = open_owner4(0, "My Open Owner") how = openflag4(OPEN4_CREATE, createhow4(GUARDED4, {FATTR4_SIZE:0})) claim = open_claim4(CLAIM_NULL, env.testname(t)) open_op = op.open(0, OPEN4_SHARE_ACCESS_BOTH , OPEN4_SHARE_DENY_NONE, owner, how, claim) fh_op = op.putrootfh() res = sess1.compound([fh_op, open_op, op.getfh()]) # OPEN print res check(res) fh = res.resarray[-1].object stateid = res.resarray[-2].stateid stateid.seqid = 0 res = sess1.compound([op.putfh(fh), op.write(stateid, 5, FILE_SYNC4, "write test data")]) print res check(res) res = sess1.compound([op.putfh(fh), op.read(stateid, 0, 1000)]) print res check(res)
def lookup_obj(sess, path): compound = [op.putrootfh()] compound += [op.lookup(comp) for comp in path] compound += [op.getfh()] res = sess.compound(compound) check(res) return res.resarray[-1].object
def testReadWrite(t, env): """Do a simple READ and WRITE FLAGS: open all CODE: OPEN400 """ c1 = env.c1.new_client(env.testname(t)) sess1 = c1.create_session() owner = open_owner4(0, "My Open Owner") how = openflag4(OPEN4_CREATE, createhow4(GUARDED4, {FATTR4_SIZE: 0})) claim = open_claim4(CLAIM_NULL, env.testname(t)) open_op = op.open(0, OPEN4_SHARE_ACCESS_BOTH, OPEN4_SHARE_DENY_NONE, owner, how, claim) fh_op = op.putrootfh() res = sess1.compound([fh_op, open_op, op.getfh()]) # OPEN print res check(res) fh = res.resarray[-1].object stateid = res.resarray[-2].stateid stateid.seqid = 0 res = sess1.compound( [op.putfh(fh), op.write(stateid, 5, FILE_SYNC4, "write test data")]) print res check(res) res = sess1.compound([op.putfh(fh), op.read(stateid, 0, 1000)]) print res check(res)
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 use_obj(file): """File is either None, a fh, or a list of path components""" if file is None or file == [None]: return [] elif type(file) is str: return [op.putfh(file)] else: return [op.putrootfh()] + [op.lookup(comp) for comp in file]
def testLongName(t, env): """LOOKUP should fail with NFS4ERR_NAMETOOLONG with long filenames FLAGS: lookup longname all CODE: LOOK4 """ c1 = env.c1.new_client(env.testname(t)) sess1 = c1.create_session() res = sess1.compound([op.putrootfh(), op.lookup('abc' * 512)]) check(res, NFS4ERR_NAMETOOLONG, "LOOKUP with very long component")
def testZeroLength(t, env): """LOOKUP with zero length name should return NFS4ERR_INVAL FLAGS: lookup all CODE: LOOK3 """ c1 = env.c1.new_client(env.testname(t)) sess1 = c1.create_session() res = sess1.compound([op.putrootfh(), op.lookup('')]) check(res, NFS4ERR_INVAL, "LOOKUP with no zero-length component")
def testNotOnlyOp(t, env): """Check for NFS4ERR_NOT_ONLY_OP FLAGS: exchange_id all CODE: EID8 """ c = env.c1 owner = client_owner4(c.verifier, env.testname(t)) protect = state_protect4_a(SP4_NONE) res = c.compound([op.exchange_id(owner, 0, protect, [c.impl_id]), op.putrootfh()]) # per draft 21 18.35.3, server MUST return NFS4ERR_NOT_ONLY_OP check(res, NFS4ERR_NOT_ONLY_OP)
def testOpenPutrootfhClose(t, env): """test current state id processing by having OPEN, PUTROOTFH and CLOSE in a single compound FLAGS: currentstateid all CODE: CSID5 """ sess1 = env.c1.new_client_session(env.testname(t)) open_op = open_create_file_op(sess1, env.testname(t), open_create=OPEN4_CREATE) res = sess1.compound(open_op + [op.putrootfh(), op.close(0, current_stateid)]) checklist(res, [NFS4ERR_STALE_STATEID, NFS4ERR_BAD_STATEID])
def testLookuppRoot(t, env): """Lookupp from root should return NFS4ERR_NOENT FLAGS: lookupp all CODE: LKPP2 """ c1 = env.c1.new_client(env.testname(t)) sess1 = c1.create_session() res = sess1.compound([op.putrootfh(), op.getfh()]) check(res) fh = res.resarray[-1].object res = sess1.compound([op.putfh(fh), op.lookupp()]) check(res, NFS4ERR_NOENT)
def testSupported(t, env): """Do a simple SECINFO_NO_NAME send PUTROOTFH+SECINFO_NO_NAME, check is result legal FLAGS: all secinfo_no_name CODE: SECNN1 """ c = env.c1.new_client(env.testname(t)) sess = c.create_session() # Do a simple SECINFO_NO_NAME res = sess.compound([op.putrootfh(), op.secinfo_no_name(0)]) check(res)
def testOpNotInSession(t, env): """Operations other than SEQUENCE, BIND_CONN_TO_SESSION, EXCHANGE_ID, CREATE_SESSION, and DESTROY_SESSION, MUST NOT appear as the first operation in a COMPOUND. rfc5661 18.46.3 FLAGS: sequence all CODE: SEQ11 """ c = env.c1.new_client(env.testname(t)) # putrootfh with out session res = c.c.compound([op.putrootfh()]) check(res, NFS4ERR_OP_NOT_IN_SESSION)
def testNotOnlyOp(t, env): """Check for NFS4ERR_NOT_ONLY_OP FLAGS: create_session all CODE: CSESS23 """ c = env.c1.new_client(env.testname(t)) # CREATE_SESSION with PUT_ROOTFH chan_attrs = channel_attrs4(0,8192,8192,8192,128,8,[]) res = c.c.compound([op.create_session(c.clientid, c.seqid, 0, chan_attrs, chan_attrs, 123, []), op.putrootfh()], None) check(res, NFS4ERR_NOT_ONLY_OP)
def testSupported3(t, env): """Do a SECINFO_NO_NAME(SECINFO_STYLE4_PARENT) of root FH, expect NFS4ERR_NOENT send PUTROOTFH+SECINFO_NO_NAME(SECINFO_STYLE4_PARENT), check is result NOENT FLAGS: all secinfo_no_name CODE: SECNN3 """ c = env.c1.new_client(env.testname(t)) sess = c.create_session() # Do a simple SECINFO_NO_NAME res = sess.compound([op.putrootfh(), op.secinfo_no_name(SECINFO_STYLE4_PARENT)]) check(res, NFS4ERR_NOENT)
def testSupported2(t, env): """GETFH after do a SECINFO_NO_NAME or SECINFO result in a NOFILEHANDLE error, See rfc 5661 section 2.6.3.1.1.8 FLAGS: all secinfo_no_name CODE: SECNN2 """ c = env.c1.new_client(env.testname(t)) sess = c.create_session() # GETFH after do a SECINFO_NO_NAME should get error NFS4ERR_NOFILEHANDLE res = sess.compound([op.putrootfh(), op.secinfo_no_name(0), op.getfh()]) print res check(res, NFS4ERR_NOFILEHANDLE)
def testSupported(t, env): """Do a simple RECLAIM_COMPLETE FLAGS: reclaim_complete all CODE: RECC1 """ c = env.c1.new_client(env.testname(t)) sess = c.create_session() res = sess.compound([op.putrootfh(), op.reclaim_complete(TRUE)]) check(res) res = sess.compound([op.reclaim_complete(FALSE)]) check(res)
def testRequestTooBig(t, env): """Send a request bigger than session can handle FLAGS: sequence all CODE: SEQ6 """ c1 = env.c1.new_client(env.testname(t)) # Only allow 512 byte requests attrs = channel_attrs4(0, 512, 8192, 8192, 128, 8, []) sess1 = c1.create_session(fore_attrs = attrs) # Send a lookup request with a very long filename res = sess1.compound([op.putrootfh(), op.lookup("12345"*100)]) # FIXME - NAME_TOO_BIG is valid, don't want it to be check(res, NFS4ERR_REQ_TOO_BIG)
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 testSupported2(t, env): """Do a CREATE_SESSION after a SEQUENCE (for same client) FLAGS: create_session all CODE: CSESS2 """ c1 = env.c1.new_client(env.testname(t)) sess1 = c1.create_session() # Create second session chan_attrs = channel_attrs4(0,8192,8192,8192,128,8,[]) cs_op = op.create_session(c1.clientid, c1.seqid, 0, chan_attrs, chan_attrs, c1.c.prog, []) res = sess1.compound([cs_op]) check(res) sess2 = c1._add_session(res.resarray[-1]) # Now make sure sess2 works res = sess2.compound([op.putrootfh()]) check(res)
def testXdev(t, env): """LOOKUPP with dir on different fs FLAGS: special CODE: LKPP4 """ c1 = env.c1.new_client(env.testname(t)) sess1 = c1.create_session() ops = [op.putrootfh(), op.getfh()] op_pairs = [(op.lookup(component), op.getfh()) for component in env.opts.usespecial] ops += [op_pair[i] for op_pair in op_pairs for i in range(2)] ops += [op.lookupp(), op.getfh()] res = sess1.compound(ops) check(res) fh1 = res.resarray[-5].object fh2 = res.resarray[-1].object if fh1 != fh2: t.fail("file handles not equal")
def testTooManyOps(t, env): """Send a request with more ops than the session can handle FLAGS: sequence all CODE: SEQ7 """ c1 = env.c1.new_client(env.testname(t)) # Create session asking for 4 ops max per request attrs = channel_attrs4(0, 8192, 8192, 8192, 4, 8, []) sess1 = c1.create_session(fore_attrs = attrs) # Send the max number of ops allowed by the server lots_of_ops = [op.putrootfh(), op.getfh()] lots_of_ops += [op.getattr(0) for num in xrange(sess1.fore_channel.maxoperations-3)] res = sess1.compound(lots_of_ops) check(res) # Add one more op to exceed the maximum lots_of_ops += [op.getattr(0)] res = sess1.compound(lots_of_ops) check(res, NFS4ERR_TOO_MANY_OPS)
def testSupported2b(t, env): """Do a CREATE_SESSION after a SEQUENCE (for different client) FLAGS: create_session all CODE: CSESS2b """ c1 = env.c1.new_client("%s_1" % env.testname(t)) c2 = env.c1.new_client("%s_2" % env.testname(t)) sess1 = c1.create_session() # Create second session chan_attrs = channel_attrs4(0,8192,8192,8192,128,8,[]) sec = [callback_sec_parms4(0)] cs_op = op.create_session(c2.clientid, c2.seqid, 0, chan_attrs, chan_attrs, c2.c.prog, sec) res = sess1.compound([cs_op]) check(res) sess2 = c2._add_session(res.resarray[-1]) # Now make sure sess2 works res = sess2.compound([op.putrootfh()]) check(res)
def _getleasetime(sess): res = sess.compound([op.putrootfh(), op.getattr(1 << FATTR4_LEASE_TIME)]) return res.resarray[-1].obj_attributes[FATTR4_LEASE_TIME]