2014-06-05 13:55:48

by Weston Andros Adamson

[permalink] [raw]
Subject: [PATCH pynfs v2 00/16] prep for flex file layout server

Changes in v2:

- moved "4.1 client: reclaim_complete after create_session" to
"dataserver: reclaim_complete after create_session" as the implicit
reclaim complete is needed in DS path, but not in all server tests.

- dropped "4.1 server: service RECLAIM_COMPLETE operations" as it's
unneeded.

- formatted these patches with -M flag so we can see moved files

.. and I pushed the changes to my ff_prep branch.

Thanks!
-dros


These patches are in preparation for the pynfs implementation of a flex
file layout server.

I already have patches for a working flex file server, but I figure those
should wait until the spec is complete ;)

I pushed these patches to my linux-nfs.org tree on branch 'ff_prep':

git://git.linux-nfs.org/projects/dros/pynfs.git

The prep includes:

- patches that enable pynfs mds using real v4.1 DSes (on the backend,
not usable from clients as there is no stateid sharing between mds and ds)

- fix several bugs in pnfs path

- move .x files to subdir 'xdrdef' - the nfs4.1 directory was getting crowded
and we're going to add several more .x files along with all of the
autogenerated files. Note this change touches server tests too.

- clean up the nfs4server's output - no longer print out EVERY part of EVERY
operation which was very efficient at hiding tracebacks and made pynfs
even slower. Old functionality is now switched on with -v flag. Also
added an in-between mode "-s" that prints a summary of whats going on.

- support for NFSv3 backend communication - this is not actually used yet,
but can be tested with file layout by always returning
NFS4ERR_LAYOUTUNAVAILABLE in layoutget and using DataServer3 class instead
of DataServer41


Weston Andros Adamson (16):
dataserver: reclaim_complete after create_session
dataserver: only catch connection error
4.1 server: avoid traceback in DS disconnect()
move .x files to subdir 'xdrdef'
4.1 client: remove unused imports
4.1 server: add -v flag & silence random output
4.1 server: add -s option to print summary of ops
dataserver: make generic interface to ops
dataserver: don't import * from nfs4 specific mods
4.1 server: move nfs4_ops.py to nfs_ops.py
add mntv3, portmapv2 and nfsv3 .x files
dataserver: separate generic and 4.1 code
4.1 server: add support for NFSv3 data servers
4.1 server: get rid of old op_getdeviceinfo
rpc: on socket error, close and mark pipe inactive
nfs3clnt: reconnect when sending on inactive pipe

nfs4.1/block.py | 8 +-
nfs4.1/client41tests/environment.py | 4 +-
nfs4.1/config.py | 8 +-
nfs4.1/dataserver.py | 308 ++++++++---
nfs4.1/fs.py | 38 +-
nfs4.1/nfs3client.py | 185 +++++++
nfs4.1/nfs4_ops.py | 61 ---
nfs4.1/nfs4client.py | 47 +-
nfs4.1/nfs4commoncode.py | 10 +-
nfs4.1/nfs4lib.py | 62 ++-
nfs4.1/nfs4server.py | 163 +++---
nfs4.1/nfs4state.py | 15 +-
nfs4.1/nfs_ops.py | 89 +++
nfs4.1/server41tests/environment.py | 4 +-
nfs4.1/server41tests/st_block.py | 4 +-
nfs4.1/server41tests/st_compound.py | 4 +-
nfs4.1/server41tests/st_create_session.py | 4 +-
nfs4.1/server41tests/st_current_stateid.py | 8 +-
nfs4.1/server41tests/st_debug.py | 4 +-
nfs4.1/server41tests/st_delegation.py | 4 +-
nfs4.1/server41tests/st_destroy_clientid.py | 2 +-
nfs4.1/server41tests/st_destroy_session.py | 4 +-
nfs4.1/server41tests/st_exchange_id.py | 4 +-
nfs4.1/server41tests/st_getdevicelist.py | 4 +-
nfs4.1/server41tests/st_lookup.py | 2 +-
nfs4.1/server41tests/st_lookupp.py | 2 +-
nfs4.1/server41tests/st_open.py | 8 +-
nfs4.1/server41tests/st_putfh.py | 2 +-
nfs4.1/server41tests/st_reboot.py | 4 +-
nfs4.1/server41tests/st_reclaim_complete.py | 2 +-
nfs4.1/server41tests/st_rename.py | 4 +-
nfs4.1/server41tests/st_secinfo.py | 4 +-
nfs4.1/server41tests/st_secinfo_no_name.py | 4 +-
nfs4.1/server41tests/st_sequence.py | 4 +-
nfs4.1/server41tests/st_trunking.py | 4 +-
nfs4.1/server41tests/st_verify.py | 2 +-
nfs4.1/server_exports.py | 7 +-
nfs4.1/setup.py | 33 +-
nfs4.1/testclient.py | 2 +-
nfs4.1/testserver.py | 2 +-
nfs4.1/xdrdef/__init__.py | 0
nfs4.1/xdrdef/mnt3.x | 68 +++
nfs4.1/xdrdef/nfs3.x | 818 ++++++++++++++++++++++++++++
nfs4.1/{ => xdrdef}/nfs4.x | 0
nfs4.1/{ => xdrdef}/nfs4.x.diff | 0
nfs4.1/{ => xdrdef}/pnfs_block.x | 0
nfs4.1/xdrdef/portmap.x | 51 ++
nfs4.1/{ => xdrdef}/sctrl.x | 0
rpc/rpc.py | 26 +-
49 files changed, 1704 insertions(+), 389 deletions(-)
create mode 100644 nfs4.1/nfs3client.py
delete mode 100644 nfs4.1/nfs4_ops.py
create mode 100644 nfs4.1/nfs_ops.py
create mode 100644 nfs4.1/xdrdef/__init__.py
create mode 100644 nfs4.1/xdrdef/mnt3.x
create mode 100644 nfs4.1/xdrdef/nfs3.x
rename nfs4.1/{ => xdrdef}/nfs4.x (100%)
rename nfs4.1/{ => xdrdef}/nfs4.x.diff (100%)
rename nfs4.1/{ => xdrdef}/pnfs_block.x (100%)
create mode 100644 nfs4.1/xdrdef/portmap.x
rename nfs4.1/{ => xdrdef}/sctrl.x (100%)

--
1.8.5.2 (Apple Git-48)



2014-06-05 13:55:51

by Weston Andros Adamson

[permalink] [raw]
Subject: [PATCH pynfs v2 02/16] dataserver: only catch connection error

This specifically checks for the error being reported, otherwise a
other exceptions like a programming error will be caught and treated
as connection errors.

Signed-off-by: Weston Andros Adamson <[email protected]>
---
nfs4.1/dataserver.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/nfs4.1/dataserver.py b/nfs4.1/dataserver.py
index ade55e1..aca07ee 100644
--- a/nfs4.1/dataserver.py
+++ b/nfs4.1/dataserver.py
@@ -9,6 +9,7 @@ import nfs4client
import hashlib
import sys
import nfs4_ops as op
+import socket

log = logging.getLogger("Dataserver Manager")

@@ -198,7 +199,7 @@ class DSDevice(object):
ds = DataServer(server, port, path, mdsds=self.mdsds,
multipath_servers=server_list)
self.list.append(ds)
- except:
+ except socket.error:
log.critical("cannot access %s:%i/%s" %
(server, port, '/'.join(path)))
sys.exit(1)
--
1.8.5.2 (Apple Git-48)


2014-06-05 13:55:55

by Weston Andros Adamson

[permalink] [raw]
Subject: [PATCH pynfs v2 06/16] 4.1 server: add -v flag & silence random output

By default the nfs4server spews so much information to stdout/stderr
that it's almost useless. Add the -v flag (aka --verbose) to enable
the old output.

Also remove some random prints and change some to log.info().

Signed-off-by: Weston Andros Adamson <[email protected]>
---
nfs4.1/dataserver.py | 3 +--
nfs4.1/fs.py | 4 ----
nfs4.1/nfs4client.py | 11 ++--------
nfs4.1/nfs4server.py | 61 +++++++++++++++++++++++-----------------------------
nfs4.1/nfs4state.py | 1 -
5 files changed, 30 insertions(+), 50 deletions(-)

diff --git a/nfs4.1/dataserver.py b/nfs4.1/dataserver.py
index acca210..c400d22 100644
--- a/nfs4.1/dataserver.py
+++ b/nfs4.1/dataserver.py
@@ -182,7 +182,7 @@ class DSDevice(object):
line = line.strip()
if not line or line.startswith('#'):
continue
- print "Analyzing: %r" % line
+ log.info("Analyzing: %r" % line)
try:
server_list, path = nfs4lib.parse_nfs_url(line)
except:
@@ -192,7 +192,6 @@ class DSDevice(object):
# for now, just use the last path for local connections
server, port = server_list[-1]
server_list = server_list[:-1]
- print server, port, path
try:
log.info("Adding dataserver ip:%s port:%s path:%s" %
(server, port, '/'.join(path)))
diff --git a/nfs4.1/fs.py b/nfs4.1/fs.py
index 3d63ce5..6ef283b 100644
--- a/nfs4.1/fs.py
+++ b/nfs4.1/fs.py
@@ -13,7 +13,6 @@ from xdrdef.nfs4_pack import NFS4Packer
log_o = logging.getLogger("fs.obj")
log_fs = logging.getLogger("fs")
logging.addLevelName(5, "FUNCT")
-log_fs.setLevel(20)

class MetaData(object):
"""Contains everything that needs to be stored
@@ -743,7 +742,6 @@ class ConfigObj(FSObject):
line = line.strip()
if line and not line.startswith("#"):
lines.append(line)
- print lines
if len(lines) != 1:
self._reset()
return
@@ -1154,7 +1152,6 @@ class LayoutFSObj(FSObject):
disk_offset,
e.state))
block_layout = pnfs_block_layout4(elist)
- print block_layout
p = block.Packer()
p.pack_pnfs_block_layout4(block_layout)
## if self.id <= 4:
@@ -1194,7 +1191,6 @@ class LayoutFSObj(FSObject):
log_o.exception("Problem decoding opaque")
raise NFS4Error(NFS4ERR_BADLAYOUT, tag="Error decoding opaque")
upd_list = update.blu_commit_list
- print upd_list
# Error check
for e in upd_list:
if e.bex_state != block.PNFS_BLOCK_READWRITE_DATA:
diff --git a/nfs4.1/nfs4client.py b/nfs4.1/nfs4client.py
index 7a07ab7..0ba84bd 100644
--- a/nfs4.1/nfs4client.py
+++ b/nfs4.1/nfs4client.py
@@ -19,9 +19,7 @@ import logging
logging.basicConfig(level=logging.INFO,
format="%(levelname)-7s:%(name)s:%(message)s")
log_cb = logging.getLogger("nfs.client.cb")
-log_cb.setLevel(logging.DEBUG)

-SHOW_TRAFFIC = True # Debugging aid, prints out client traffic
class NFS4Client(rpc.Client, rpc.Server):
def __init__(self, host='localhost', port=2049, minorversion=1, ctrl_proc=16):
rpc.Client.__init__(self, 100003, 4)
@@ -76,9 +74,7 @@ class NFS4Client(rpc.Client, rpc.Server):
pipe = self.c1
p = packer(check_enum=checks, check_array=checks)
c4 = COMPOUND4args(tag, version, ops)
- if SHOW_TRAFFIC:
- print
- print c4
+ log_cb.info("compound args = %r" % (c4,))
p.pack_COMPOUND4args(c4)
return self.send_call(pipe, 1, p.get_buffer(), credinfo)

@@ -86,19 +82,16 @@ class NFS4Client(rpc.Client, rpc.Server):
xid = self.compound_async(*args, **kwargs)
pipe = kwargs.get("pipe", None)
res = self.listen(xid, pipe=pipe)
- if SHOW_TRAFFIC:
- print res
+ log_cb.info("compound result = %r" % (res,))
return res

def listen(self, xid, pipe=None, timeout=10.0):
if pipe is None:
pipe = self.c1
header, data = pipe.listen(xid, timeout)
- #print "HEADER", header
if data:
p = nfs4lib.FancyNFS4Unpacker(data)
data = p.unpack_COMPOUND4res()
- #print "DATA", repr(data)
return data

def handle_0(self, data, cred):
diff --git a/nfs4.1/nfs4server.py b/nfs4.1/nfs4server.py
index 2ae99fe..a495d3c 100755
--- a/nfs4.1/nfs4server.py
+++ b/nfs4.1/nfs4server.py
@@ -21,14 +21,11 @@ from nfs4commoncode import CompoundState, encode_status, encode_status_by_name
from fs import RootFS, ConfigFS
from config import ServerConfig, ServerPerClientConfig, OpsConfigServer, Actions

-logging.basicConfig(level=logging.INFO,
+logging.basicConfig(level=logging.WARN,
format="%(levelname)-7s:%(name)s:%(message)s")
log_41 = logging.getLogger("nfs.server")
-log_41.setLevel(logging.DEBUG)
-log_41.setLevel(9)

log_cfg = logging.getLogger("nfs.server.opconfig")
-log_cfg.setLevel(20)

##################################################
# Set various global constants and magic numbers #
@@ -116,9 +113,6 @@ class Recording(object):
def add(self, call, reply):
"""Add call and reply strings to records"""
if self.on:
- print "Adding"
- print repr(call)
- print repr(reply)
self.queue.appendleft((call, reply))

def set_stamp(self, stamp):
@@ -269,13 +263,13 @@ class VerboseDict(dict):
self.config = config

def __setitem__(self, key, value):
- if 0 or self.config.debug_state:
- print "+++ Adding client.state[%r]" % key
+ if self.config.debug_state:
+ log_41.info("+++ Adding client.state[%r]" % key)
dict.__setitem__(self, key, value)

def __delitem__(self, key):
- if 0 or self.config.debug_state:
- print "+++ Removing client.state[%r]" % key
+ if self.config.debug_state:
+ log_41.info("+++ Removing client.state[%r]" % key)
dict.__delitem__(self, key)

class ClientRecord(object):
@@ -526,6 +520,13 @@ class NFS4Server(rpc.Server):
port = kwargs.pop("port", NFS4_PORT)
self.is_mds = kwargs.pop("is_mds", False)
self.is_ds = kwargs.pop("is_ds", False)
+
+ self.verbose = kwargs.pop('verbose', False)
+ if self.verbose:
+ log_41.setLevel(logging.DEBUG) # XXX redundant?
+ log_41.setLevel(9)
+ log_cfg.setLevel(20)
+
rpc.Server.__init__(self, prog=NFS4_PROGRAM, versions=[4], port=port,
**kwargs)
self.root = RootFS().root # Root of exported filesystem tree
@@ -552,7 +553,7 @@ class NFS4Server(rpc.Server):
rpc.Server.start(self)
except KeyboardInterrupt:
# Put user into console where can look at state of server
- if not self.config.catch_ctrlc:
+ if not self.config.catch_ctrlc or not self.verbose:
raise
import code
import readline
@@ -1330,9 +1331,9 @@ class NFS4Server(rpc.Server):
sid, deleg, flags = self.open_file(existing, arg.owner,
arg.share_access, arg.share_deny)
env.set_cfh(existing, sid)
- if 0 or env.session.client.config.debug_state:
- print "+++ client(id=%i).state =" % env.session.client.clientid
- print env.session.client.state
+ if env.session.client.config.debug_state:
+ log_41.info("+++ client(id=%i).state = %r" %
+ (env.session.client.clientid, env.session.client.state))
res = OPEN4resok(sid, cinfo, flags, bitmask, deleg)
return encode_status(NFS4_OK, res)

@@ -1452,14 +1453,13 @@ class NFS4Server(rpc.Server):
ret_dict = {}
info = nfs4lib.attr_info
for attr in attrs:
- print "handling fattr4_%s : " % nfs4lib.attr_name(attr),
if attr not in info:
# Ignore unknown attributes
- print "Unknown"
+ log_41.info("Skipping unknown attr: %s" % (attr,))
continue
if not info[attr].readable:
# XXX How deal with write-only attrs?
- print "Write only"
+ log_41.info("Skipping write only attr: %s" % (attr,))
continue
# Attributes hide in different places, call the place 'base'
if info[attr].from_fs:
@@ -1471,24 +1471,14 @@ class NFS4Server(rpc.Server):
name = "fattr4_%s" % nfs4lib.attr_name(attr)
if hasattr(base, name) and (obj.fs.fattr4_supported_attrs & 1<<attr): # STUB we should be able to remove hasattr
ret_dict[attr] = getattr(base, name)
- print ret_dict[attr]
else:
if ignore:
# Must ignore for GETATTR (and READDIR) per 15.1
- print "ignored"
- if name == "fattr4_mounted_on_fileid":
- print base == obj
- print base.fattr4_mounted_on_fileid
- if name == "fattr4_layout_blksize":
- print base == obj
- print hasattr(base, name)
- print obj.fs.fattr4_supported_attrs
- print 1<<attr
- print obj.fs.fattr4_supported_attrs & 1<<attr
+ log_41.info("ignored attr %s" % (name,))
continue
else:
# This is for VERIFY/NVERIFY
- print "NOT SUPP"
+ log_41.info("attr NOT SUPP %s" % (name,))
raise NFS4Error(NFS4ERR_ATTRNOTSUPP)
obj.fattr4_rdattr_error = NFS4_OK # XXX STUB Handle correctly
return ret_dict
@@ -1953,14 +1943,14 @@ class NFS4Server(rpc.Server):
calls.append(call)
if arg.dir & xdrdef.sctrl_const.DIR_REPLY:
replies.append(reply)
- print calls
- print replies
+ #print calls
+ #print replies
grabres = xdrdef.sctrl_type.GRABres(calls, replies)
return xdrdef.sctrl_const.CTRLSTAT_OK, \
xdrdef.sctrl_type.resdata_t(arg.ctrlop, grab = grabres)

def ctrl_illegal(self, arg):
- print "ILLEGAL"
+ #print "ILLEGAL"
return xdrdef.sctrl_const.CTRLSTAT_ILLEGAL, xdrdef.sctrl_type.resdata_t(arg.ctrlop)

def op_setclientid(self, arg, env):
@@ -2067,6 +2057,8 @@ def scan_options():
)
p.add_option("-r", "--reset", action="store_true", default=False,
help="Reset and clear any disk-based filesystems")
+ p.add_option("-v", "--verbose", action="store_true", default=False,
+ help="Print debug info to screen and enter interpreter on ^C")
p.add_option("--use_block", action="store_true", default=False,
help="Mount a block-pnfs fs")
p.add_option("--use_files", action="store_true", default=False,
@@ -2099,7 +2091,8 @@ if __name__ == "__main__":
locking.DEBUG = True
S = NFS4Server(port=opts.port,
is_mds=opts.use_block or opts.use_files,
- is_ds = opts.is_ds)
+ is_ds = opts.is_ds,
+ verbose = opts.verbose)
read_exports(S, opts)
if True:
S.start()
diff --git a/nfs4.1/nfs4state.py b/nfs4.1/nfs4state.py
index 1294083..2f3cd59 100644
--- a/nfs4.1/nfs4state.py
+++ b/nfs4.1/nfs4state.py
@@ -13,7 +13,6 @@ import rpc
import logging

log = logging.getLogger("nfs.server.state")
-log.setLevel(10)

POSIXLOCK = False

--
1.8.5.2 (Apple Git-48)


2014-06-05 13:55:53

by Weston Andros Adamson

[permalink] [raw]
Subject: [PATCH pynfs v2 04/16] move .x files to subdir 'xdrdef'

In preparation for adding more .x files, clean up the main nfs4.1 dir
by moving these files (and autogenerated files) to a subdirectory.

Signed-off-by: Weston Andros Adamson <[email protected]>
---
nfs4.1/block.py | 8 ++---
nfs4.1/client41tests/environment.py | 4 +--
nfs4.1/config.py | 8 ++---
nfs4.1/dataserver.py | 6 ++--
nfs4.1/fs.py | 8 ++---
nfs4.1/nfs4_ops.py | 4 +--
nfs4.1/nfs4client.py | 11 +++---
nfs4.1/nfs4commoncode.py | 10 +++---
nfs4.1/nfs4lib.py | 54 ++++++++++++++---------------
nfs4.1/nfs4server.py | 36 +++++++++----------
nfs4.1/nfs4state.py | 6 ++--
nfs4.1/server41tests/environment.py | 4 +--
nfs4.1/server41tests/st_block.py | 4 +--
nfs4.1/server41tests/st_compound.py | 4 +--
nfs4.1/server41tests/st_create_session.py | 4 +--
nfs4.1/server41tests/st_current_stateid.py | 8 ++---
nfs4.1/server41tests/st_debug.py | 4 +--
nfs4.1/server41tests/st_delegation.py | 4 +--
nfs4.1/server41tests/st_destroy_clientid.py | 2 +-
nfs4.1/server41tests/st_destroy_session.py | 4 +--
nfs4.1/server41tests/st_exchange_id.py | 4 +--
nfs4.1/server41tests/st_getdevicelist.py | 4 +--
nfs4.1/server41tests/st_lookup.py | 2 +-
nfs4.1/server41tests/st_lookupp.py | 2 +-
nfs4.1/server41tests/st_open.py | 8 ++---
nfs4.1/server41tests/st_putfh.py | 2 +-
nfs4.1/server41tests/st_reboot.py | 4 +--
nfs4.1/server41tests/st_reclaim_complete.py | 2 +-
nfs4.1/server41tests/st_rename.py | 4 +--
nfs4.1/server41tests/st_secinfo.py | 4 +--
nfs4.1/server41tests/st_secinfo_no_name.py | 4 +--
nfs4.1/server41tests/st_sequence.py | 4 +--
nfs4.1/server41tests/st_trunking.py | 4 +--
nfs4.1/server41tests/st_verify.py | 2 +-
nfs4.1/setup.py | 33 ++++++++++--------
nfs4.1/testclient.py | 2 +-
nfs4.1/testserver.py | 2 +-
nfs4.1/xdrdef/__init__.py | 0
nfs4.1/{ => xdrdef}/nfs4.x | 0
nfs4.1/{ => xdrdef}/nfs4.x.diff | 0
nfs4.1/{ => xdrdef}/pnfs_block.x | 0
nfs4.1/{ => xdrdef}/sctrl.x | 0
42 files changed, 141 insertions(+), 139 deletions(-)
create mode 100644 nfs4.1/xdrdef/__init__.py
rename nfs4.1/{ => xdrdef}/nfs4.x (100%)
rename nfs4.1/{ => xdrdef}/nfs4.x.diff (100%)
rename nfs4.1/{ => xdrdef}/pnfs_block.x (100%)
rename nfs4.1/{ => xdrdef}/sctrl.x (100%)

diff --git a/nfs4.1/block.py b/nfs4.1/block.py
index 2201550..f37bd9b 100644
--- a/nfs4.1/block.py
+++ b/nfs4.1/block.py
@@ -1,8 +1,8 @@
from __future__ import with_statement
-from pnfs_block_pack import PNFS_BLOCKPacker as Packer
-from pnfs_block_pack import PNFS_BLOCKUnpacker as Unpacker
-from pnfs_block_type import *
-from pnfs_block_const import *
+from xdrdef.pnfs_block_pack import PNFS_BLOCKPacker as Packer
+from xdrdef.pnfs_block_pack import PNFS_BLOCKUnpacker as Unpacker
+from xdrdef.pnfs_block_type import *
+from xdrdef.pnfs_block_const import *

import fs_base
from threading import Lock
diff --git a/nfs4.1/client41tests/environment.py b/nfs4.1/client41tests/environment.py
index 84b7d38..225197f 100644
--- a/nfs4.1/client41tests/environment.py
+++ b/nfs4.1/client41tests/environment.py
@@ -10,8 +10,8 @@

import time
import testmod
-from nfs4_const import *
-from nfs4_type import *
+from xdrdef.nfs4_const import *
+from xdrdef.nfs4_type import *
import rpc
import nfs4client
import os
diff --git a/nfs4.1/config.py b/nfs4.1/config.py
index 2238aee..4747f73 100644
--- a/nfs4.1/config.py
+++ b/nfs4.1/config.py
@@ -1,6 +1,6 @@
-from nfs4_type import server_owner4, nfs_impl_id4
-from nfs4_const import *
-import nfs4_const
+from xdrdef.nfs4_type import server_owner4, nfs_impl_id4
+from xdrdef.nfs4_const import *
+import xdrdef.nfs4_const
import nfs4lib
from copy import deepcopy
import os
@@ -37,7 +37,7 @@ def _statcode(value):
try:
return int(value)
except ValueError:
- rv = getattr(nfs4_const, value, None)
+ rv = getattr(xdr.nfs4_const, value, None)
if rv is None or nfsstat4.get(rv, None) != value:
raise
else:
diff --git a/nfs4.1/dataserver.py b/nfs4.1/dataserver.py
index 435ddd2..acca210 100644
--- a/nfs4.1/dataserver.py
+++ b/nfs4.1/dataserver.py
@@ -1,8 +1,8 @@
import rpc
import nfs4lib
-from nfs4_type import *
-from nfs4_pack import NFS4Packer
-from nfs4_const import *
+from xdrdef.nfs4_type import *
+from xdrdef.nfs4_pack import NFS4Packer
+from xdrdef.nfs4_const import *
import time
import logging
import nfs4client
diff --git a/nfs4.1/fs.py b/nfs4.1/fs.py
index a63c5bf..3d63ce5 100644
--- a/nfs4.1/fs.py
+++ b/nfs4.1/fs.py
@@ -1,6 +1,6 @@
from nfs4state import FileState
-from nfs4_const import *
-from nfs4_type import fsid4, layout4, layout_content4, nfsv4_1_file_layout4
+from xdrdef.nfs4_const import *
+from xdrdef.nfs4_type import fsid4, layout4, layout_content4, nfsv4_1_file_layout4
import nfs4lib
from nfs4lib import NFS4Error
import struct
@@ -8,7 +8,7 @@ import logging
from locking import Lock, RWLock
from cStringIO import StringIO
import time
-from nfs4_pack import NFS4Packer
+from xdrdef.nfs4_pack import NFS4Packer

log_o = logging.getLogger("fs.obj")
log_fs = logging.getLogger("fs")
@@ -1070,7 +1070,7 @@ class StubFS_Disk(FileSystem):

###################################################

-from pnfs_block_type import pnfs_block_extent4, pnfs_block_layout4
+from xdrdef.pnfs_block_type import pnfs_block_extent4, pnfs_block_layout4
import block

class my_ro_extent(object):
diff --git a/nfs4.1/nfs4_ops.py b/nfs4.1/nfs4_ops.py
index 75381b6..35a10ca 100644
--- a/nfs4.1/nfs4_ops.py
+++ b/nfs4.1/nfs4_ops.py
@@ -2,8 +2,8 @@
<name>() that returns the appropriate *_argop4 structure, hiding
this routine packing from the user.
"""
-import nfs4_type as _type
-import nfs4_const as _const
+import xdrdef.nfs4_type as _type
+import xdrdef.nfs4_const as _const

# This string is our general function template
code = """\
diff --git a/nfs4.1/nfs4client.py b/nfs4.1/nfs4client.py
index e750728..2aa0a2c 100644
--- a/nfs4.1/nfs4client.py
+++ b/nfs4.1/nfs4client.py
@@ -2,10 +2,9 @@ import use_local # HACK so don't have to rebuild constantly
import rpc
import nfs4lib
from nfs4lib import NFS4Error, NFS4Replay, inc_u32
-import nfs4_type, nfs4_const
-from nfs4_type import *
-from nfs4_const import *
-from sctrl_pack import SCTRLPacker, SCTRLUnpacker
+from xdrdef.nfs4_type import *
+from xdrdef.nfs4_const import *
+from xdrdef.sctrl_pack import SCTRLPacker, SCTRLUnpacker
import nfs4_ops as op
import time, struct
import threading
@@ -545,8 +544,8 @@ sec.init_cred(call)

""" EXCHANGE_ID
import nfs4client
-from nfs4_type import *
-from nfs4_const import *
+from xdrdef.nfs4_type import *
+from xdrdef.nfs4_const import *
import nfs4_ops as op
owner = client_owner4("12345678","MyClientName")
protect = state_protect4_a(SP4_NONE)
diff --git a/nfs4.1/nfs4commoncode.py b/nfs4.1/nfs4commoncode.py
index 317f04c..cadd237 100644
--- a/nfs4.1/nfs4commoncode.py
+++ b/nfs4.1/nfs4commoncode.py
@@ -4,10 +4,10 @@
"""

import nfs4lib
-from nfs4_const import *
+from xdrdef.nfs4_const import *
import sys
-import nfs4_type, nfs4_const
-from nfs4_type import *
+import xdrdef.nfs4_type, xdrdef.nfs4_const
+from xdrdef.nfs4_type import *

_d = {"CompoundState" : "CompoundState",
"PairedResults" : "PairedResults",
@@ -34,8 +34,8 @@ def %(encode_status)s_by_name(name, status, *args, **kwargs):
name_l = name.lower()
name_u = name.upper()
try:
- res4 = getattr(nfs4_type, name_u + "4res")(status, *args, **kwargs)
- result = %(nfs_resop4)s(getattr(nfs4_const, "OP_" + name_u))
+ res4 = getattr(xdrdef.nfs4_type, name_u + "4res")(status, *args, **kwargs)
+ result = %(nfs_resop4)s(getattr(xdrdef.nfs4_const, "OP_" + name_u))
setattr(result, %(mangle)s, res4)
# STUB XXX 4.1 has messed with the naming conventions,
# and added prefixes to the "status" variable. Grrr.
diff --git a/nfs4.1/nfs4lib.py b/nfs4.1/nfs4lib.py
index d1edc10..116324a 100644
--- a/nfs4.1/nfs4lib.py
+++ b/nfs4.1/nfs4lib.py
@@ -1,8 +1,8 @@
from __future__ import with_statement
import rpc
-import nfs4_const
-import nfs4_pack
-import nfs4_type
+import xdrdef.nfs4_const
+from xdrdef.nfs4_pack import NFS4Packer, NFS4Unpacker
+import xdrdef.nfs4_type
import nfs4_ops as op
import time
import collections
@@ -24,9 +24,9 @@ except ImportError:
raise NotImplementedError("could not import Crypto.Cipher")

# Special stateids
-state00 = nfs4_type.stateid4(0, "\0" * 12)
-state11 = nfs4_type.stateid4(0xffffffff, "\xff" * 12)
-state01 = nfs4_type.stateid4(1, "\0" * 12)
+state00 = xdrdef.nfs4_type.stateid4(0, "\0" * 12)
+state11 = xdrdef.nfs4_type.stateid4(0xffffffff, "\xff" * 12)
+state01 = xdrdef.nfs4_type.stateid4(1, "\0" * 12)

import hashlib # Note this requires 2.5 or higher

@@ -105,9 +105,9 @@ def set_attrbit_dicts():
{ 1: "unpack_fattr4_type", 2: "unpack_fattr4_fh_expire_type", ...}
"""
global attr2bitnum, bitnum2attr, bitnum2packer, bitnum2unpacker
- for name in dir(nfs4_const):
+ for name in dir(xdrdef.nfs4_const):
if name.startswith("FATTR4_"):
- value = getattr(nfs4_const, name)
+ value = getattr(xdrdef.nfs4_const, name)
# Sanity checking. Must be integer.
assert(type(value) is int)
attrname = name[7:].lower()
@@ -130,9 +130,9 @@ def set_flags(name, search_string=None):
mask = 0
if search_string is None:
search_string = "%s4_FLAG_" % name.upper()
- for var in dir(nfs4_const):
+ for var in dir(xdrdef.nfs4_const):
if var.startswith(search_string):
- value = getattr(nfs4_const, var)
+ value = getattr(xdrdef.nfs4_const, var)
flag_dict[value] = var
mask |= value
# Now we need to set the appropriate module level variable
@@ -187,7 +187,7 @@ class InvalidCompoundRes(NFSException):
else:
return "Invalid COMPOUND result"

-class FancyNFS4Packer(nfs4_pack.NFS4Packer):
+class FancyNFS4Packer(NFS4Packer):
"""Handle fattr4 and dirlist4 more cleanly than auto-generated methods"""
def filter_bitmap4(self, data):
out = []
@@ -208,11 +208,11 @@ class FancyNFS4Packer(nfs4_pack.NFS4Packer):
for e in data.entries[::-1]:
# print "handle", e
# This reverses the direction of the list, so start with reversed
- out = [nfs4_type.entry4(e.cookie, e.name, e.attrs, out)]
+ out = [xdrdef.nfs4_type.entry4(e.cookie, e.name, e.attrs, out)]
# Must not modify original data structure
- return nfs4_type.dirlist4(out, data.eof)
+ return xdrdef.nfs4_type.dirlist4(out, data.eof)

-class FancyNFS4Unpacker(nfs4_pack.NFS4Unpacker):
+class FancyNFS4Unpacker(NFS4Unpacker):
def filter_bitmap4(self, data):
"""Put bitmap into single long, instead of array of 32bit chunks"""
out = 0L
@@ -257,7 +257,7 @@ def dict2fattr(dict):
getattr(packer, bitnum2packer[bitnum])(value)
attr_vals += packer.get_buffer()
attrmask = list2bitmap(attrs)
- return nfs4_type.fattr4(attrmask, attr_vals);
+ return xdrdef.nfs4_type.fattr4(attrmask, attr_vals);

def fattr2dict(obj):
"""Convert a fattr4 object to a dictionary with attribute name and values.
@@ -360,10 +360,10 @@ class SSVContext(object):
"""Compute getMIC token from given data"""
# See draft26 2.10.9
p = FancyNFS4Packer()
- p.pack_ssv_mic_plain_tkn4(nfs4_type.ssv_mic_plain_tkn4(seqnum, data))
+ p.pack_ssv_mic_plain_tkn4(xdrdef.nfs4_type.ssv_mic_plain_tkn4(seqnum, data))
hash = hmac.new(key, p.get_buffer(), self.hash).digest()
p.reset()
- p.pack_ssv_mic_tkn4(nfs4_type.ssv_mic_tkn4(seqnum, hash))
+ p.pack_ssv_mic_tkn4(xdrdef.nfs4_type.ssv_mic_tkn4(seqnum, hash))
return p.get_buffer()

def getMIC(self, data):
@@ -405,13 +405,13 @@ class SSVContext(object):
p = FancyNFS4Packer()
# We need to compute pad. Easiest (though not fastest) way
# is to pack w/o padding, determine padding needed, then repack.
- input = nfs4_type.ssv_seal_plain_tkn4(cofounder, seqnum, data, "")
+ input = xdrdef.nfs4_type.ssv_seal_plain_tkn4(cofounder, seqnum, data, "")
p.pack_ssv_seal_plain_tkn4(input)
offset = len(p.get_buffer()) % blocksize
if offset:
pad = '\0' * (blocksize - offset)
p.reset()
- input = nfs4_type.ssv_seal_plain_tkn4(cofounder, seqnum, data, pad)
+ input = xdrdef.nfs4_type.ssv_seal_plain_tkn4(cofounder, seqnum, data, pad)
p.pack_ssv_seal_plain_tkn4(input)
plain_xdr = p.get_buffer()
p.reset()
@@ -421,7 +421,7 @@ class SSVContext(object):
encrypted = obj.encrypt(plain_xdr)
dir = (SSV4_SUBKEY_MIC_I2T if self.local else SSV4_SUBKEY_MIC_T2I)
hash = hmac.new(keys[dir], plain_xdr, self.hash).digest()
- token = nfs4_type.ssv_seal_cipher_tkn4(seqnum, iv, encrypted, hash)
+ token = xdrdef.nfs4_type.ssv_seal_cipher_tkn4(seqnum, iv, encrypted, hash)
p.pack_ssv_seal_cipher_tkn4(token)
return p.get_buffer()

@@ -491,7 +491,7 @@ def get_nfstime(t=None):
t = time.time()
sec = int(t)
nsec = int((t - sec) * 1000000000)
- return nfs4_type.nfstime4(sec, nsec)
+ return xdrdef.nfs4_type.nfstime4(sec, nsec)

def parse_nfs_url(url):
"""Parse [nfs://]host:port/path, format taken from rfc 2224
@@ -565,7 +565,7 @@ def attr_name(bitnum):
class NFS4Error(Exception):
def __init__(self, status, attrs=0L, lock_denied=None, tag=None, check_msg=None):
self.status = status
- self.name = nfs4_const.nfsstat4[status]
+ self.name = xdrdef.nfs4_const.nfsstat4[status]
if check_msg is None:
self.msg = "NFS4 error code: %s" % self.name
else:
@@ -602,19 +602,19 @@ class NFS4Principal(object):
def __ne__(self, other):
return not self.__eq__(other)

-def check(res, expect=nfs4_const.NFS4_OK, msg=None):
+def check(res, expect=xdrdef.nfs4_const.NFS4_OK, msg=None):
if res.status == expect:
return
if type(expect) is str:
raise RuntimeError("You forgot to put 'msg=' in front "
"of check()'s string arg")
# Get text representations
- desired = nfs4_const.nfsstat4[expect]
- received = nfs4_const.nfsstat4[res.status]
+ desired = xdrdef.nfs4_const.nfsstat4[expect]
+ received = xdrdef.nfs4_const.nfsstat4[res.status]
if msg:
failedop_name = msg
elif res.resarray:
- failedop_name = nfs4_const.nfs_opnum4[res.resarray[-1].resop]
+ failedop_name = xdrdef.nfs4_const.nfs_opnum4[res.resarray[-1].resop]
else:
failedop_name = 'Compound'
msg = "%s should return %s, instead got %s" % \
@@ -647,7 +647,7 @@ class AttrConfig(object):
self._s = (kind=="serv")
self._fs = (kind=="fs")

-from nfs4_const import *
+from xdrdef.nfs4_const import *

A = AttrConfig
attr_info = { FATTR4_SUPPORTED_ATTRS : A("r", "fs"),
diff --git a/nfs4.1/nfs4server.py b/nfs4.1/nfs4server.py
index 65fb9af..2ae99fe 100755
--- a/nfs4.1/nfs4server.py
+++ b/nfs4.1/nfs4server.py
@@ -4,10 +4,10 @@ import use_local # HACK so don't have to rebuild constantly
import nfs4lib
from nfs4lib import inc_u32, NFS4Error, NFS4Replay
import rpc
-from nfs4_const import *
-from nfs4_type import *
-from sctrl_pack import SCTRLPacker, SCTRLUnpacker
-import sctrl_type, sctrl_const
+from xdrdef.nfs4_const import *
+from xdrdef.nfs4_type import *
+from xdrdef.sctrl_pack import SCTRLPacker, SCTRLUnpacker
+import xdrdef.sctrl_type, xdrdef.sctrl_const
import traceback, threading
from locking import Lock, Counter
import time
@@ -620,7 +620,7 @@ class NFS4Server(rpc.Server):
return rpc.GARBAGE_ARGS, None
log_cfg.info(repr(args))
# Handle the given control operation
- opname = sctrl_const.ctrl_opnum.get(args.ctrlop, 'ctrl_illegal')
+ opname = xdrdef.sctrl_const.ctrl_opnum.get(args.ctrlop, 'ctrl_illegal')
funct = getattr(self, opname.lower(), None)
if funct is None:
# This shouldn't happen
@@ -633,8 +633,8 @@ class NFS4Server(rpc.Server):
raise
# Now pack and return the result
p = SCTRLPacker()
- # res = sctrl_type.CTRLres(status, sctrl_type.resdata_t(args.ctrlop))
- res = sctrl_type.CTRLres(status, result)
+ # res = xdrdef.sctrl_type.CTRLres(status, xdrdef.sctrl_type.resdata_t(args.ctrlop))
+ res = xdrdef.sctrl_type.CTRLres(status, result)
p.pack_CTRLres(res)
return rpc.SUCCESS, p.get_buffer()

@@ -1926,22 +1926,22 @@ class NFS4Server(rpc.Server):

def ctrl_reset(self, arg):
self.recording.reset()
- return sctrl_const.CTRLSTAT_OK, sctrl_type.resdata_t(arg.ctrlop)
+ return xdrdef.sctrl_const.CTRLSTAT_OK, xdrdef.sctrl_type.resdata_t(arg.ctrlop)

def ctrl_record(self, arg):
self.recording.set_stamp(arg.stamp)
self.recording.on = True
- return sctrl_const.CTRLSTAT_OK, sctrl_type.resdata_t(arg.ctrlop)
+ return xdrdef.sctrl_const.CTRLSTAT_OK, xdrdef.sctrl_type.resdata_t(arg.ctrlop)

def ctrl_pause(self, arg):
self.recording.on = False
- return sctrl_const.CTRLSTAT_OK, sctrl_type.resdata_t(arg.ctrlop)
+ return xdrdef.sctrl_const.CTRLSTAT_OK, xdrdef.sctrl_type.resdata_t(arg.ctrlop)

def ctrl_grab(self, arg):
queue = self.recording.queues.get(arg.stamp, None)
if queue is None:
- return sctrl_const.CTRLSTAT_NOT_AVAIL, \
- sctrl_type.resdata_t(arg.ctrlop, sctrl_type.GRABres([],[]))
+ return xdrdef.sctrl_const.CTRLSTAT_NOT_AVAIL, \
+ xdrdef.sctrl_type.resdata_t(arg.ctrlop, xdrdef.sctrl_type.GRABres([],[]))
max = arg.number
if max == 0:
max = len(queue)
@@ -1949,19 +1949,19 @@ class NFS4Server(rpc.Server):
replies = []
for i in range(max):
call, reply = queue.pop()
- if arg.dir & sctrl_const.DIR_CALL:
+ if arg.dir & xdrdef.sctrl_const.DIR_CALL:
calls.append(call)
- if arg.dir & sctrl_const.DIR_REPLY:
+ if arg.dir & xdrdef.sctrl_const.DIR_REPLY:
replies.append(reply)
print calls
print replies
- grabres = sctrl_type.GRABres(calls, replies)
- return sctrl_const.CTRLSTAT_OK, \
- sctrl_type.resdata_t(arg.ctrlop, grab = grabres)
+ grabres = xdrdef.sctrl_type.GRABres(calls, replies)
+ return xdrdef.sctrl_const.CTRLSTAT_OK, \
+ xdrdef.sctrl_type.resdata_t(arg.ctrlop, grab = grabres)

def ctrl_illegal(self, arg):
print "ILLEGAL"
- return sctrl_const.CTRLSTAT_ILLEGAL, sctrl_type.resdata_t(arg.ctrlop)
+ return xdrdef.sctrl_const.CTRLSTAT_ILLEGAL, xdrdef.sctrl_type.resdata_t(arg.ctrlop)

def op_setclientid(self, arg, env):
return encode_status(NFS4ERR_NOTSUPP)
diff --git a/nfs4.1/nfs4state.py b/nfs4.1/nfs4state.py
index e8445e3..1294083 100644
--- a/nfs4.1/nfs4state.py
+++ b/nfs4.1/nfs4state.py
@@ -5,9 +5,9 @@ from locking import Lock
import struct
import nfs4lib
from nfs4lib import NFS4Error
-#from nfs4_type import stateid4
-from nfs4_type import *
-from nfs4_const import *
+#from xdrdef.nfs4_type import stateid4
+from xdrdef.nfs4_type import *
+from xdrdef.nfs4_const import *
import nfs4_ops as op
import rpc
import logging
diff --git a/nfs4.1/server41tests/environment.py b/nfs4.1/server41tests/environment.py
index b2df732..b8b05cf 100644
--- a/nfs4.1/server41tests/environment.py
+++ b/nfs4.1/server41tests/environment.py
@@ -10,8 +10,8 @@

import time
import testmod
-from nfs4_const import *
-from nfs4_type import *
+from xdrdef.nfs4_const import *
+from xdrdef.nfs4_type import *
import rpc
import nfs4client
import sys
diff --git a/nfs4.1/server41tests/st_block.py b/nfs4.1/server41tests/st_block.py
index f62968e..432dbbf 100644
--- a/nfs4.1/server41tests/st_block.py
+++ b/nfs4.1/server41tests/st_block.py
@@ -1,5 +1,5 @@
-from nfs4_const import *
-from nfs4_type import *
+from xdrdef.nfs4_const import *
+from xdrdef.nfs4_type import *
import nfs4_ops as op
from environment import check, fail, create_file
from block import Packer as BlockPacker, Unpacker as BlockUnpacker, \
diff --git a/nfs4.1/server41tests/st_compound.py b/nfs4.1/server41tests/st_compound.py
index c6a5ea9..0443a29 100644
--- a/nfs4.1/server41tests/st_compound.py
+++ b/nfs4.1/server41tests/st_compound.py
@@ -1,7 +1,7 @@
-from nfs4_const import *
+from xdrdef.nfs4_const import *
import nfs4_ops as op
from environment import check, fail, get_invalid_utf8strings
-from nfs4_type import *
+from xdrdef.nfs4_type import *
from rpc import RPCAcceptError, GARBAGE_ARGS, RPCTimeout
from nfs4lib import NFS4Error, hash_oids, encrypt_oids, FancyNFS4Packer

diff --git a/nfs4.1/server41tests/st_create_session.py b/nfs4.1/server41tests/st_create_session.py
index ae5ca27..4685eb0 100644
--- a/nfs4.1/server41tests/st_create_session.py
+++ b/nfs4.1/server41tests/st_create_session.py
@@ -1,7 +1,7 @@
-from nfs4_const import *
+from xdrdef.nfs4_const import *
import nfs4_ops as op
from environment import check, fail, create_file, open_file
-from nfs4_type import *
+from xdrdef.nfs4_type import *
import random
import nfs4lib
import threading
diff --git a/nfs4.1/server41tests/st_current_stateid.py b/nfs4.1/server41tests/st_current_stateid.py
index 9a1adc4..b2e69c5 100644
--- a/nfs4.1/server41tests/st_current_stateid.py
+++ b/nfs4.1/server41tests/st_current_stateid.py
@@ -1,11 +1,11 @@
from st_create_session import create_session
-from nfs4_const import *
+from xdrdef.nfs4_const import *

from environment import check, checklist, fail, create_file, open_file, close_file
from environment import open_create_file_op, use_obj
-from nfs4_type import open_owner4, openflag4, createhow4, open_claim4
-from nfs4_type import creatverfattr, fattr4, stateid4, locker4, lock_owner4
-from nfs4_type import open_to_lock_owner4
+from xdrdef.nfs4_type import open_owner4, openflag4, createhow4, open_claim4
+from xdrdef.nfs4_type import creatverfattr, fattr4, stateid4, locker4, lock_owner4
+from xdrdef.nfs4_type import open_to_lock_owner4
import nfs4_ops as op
import threading

diff --git a/nfs4.1/server41tests/st_debug.py b/nfs4.1/server41tests/st_debug.py
index aff6842..7bf6b5b 100644
--- a/nfs4.1/server41tests/st_debug.py
+++ b/nfs4.1/server41tests/st_debug.py
@@ -1,7 +1,7 @@
from st_create_session import create_session
-from nfs4_const import *
+from xdrdef.nfs4_const import *
from environment import check, fail, create_file
-from nfs4_type import open_owner4, openflag4, createhow4, open_claim4
+from xdrdef.nfs4_type import open_owner4, openflag4, createhow4, open_claim4
import nfs4_ops as op
import threading

diff --git a/nfs4.1/server41tests/st_delegation.py b/nfs4.1/server41tests/st_delegation.py
index 02ce719..5abc904 100644
--- a/nfs4.1/server41tests/st_delegation.py
+++ b/nfs4.1/server41tests/st_delegation.py
@@ -1,9 +1,9 @@
from st_create_session import create_session
from st_open import open_claim4
-from nfs4_const import *
+from xdrdef.nfs4_const import *

from environment import check, checklist, fail, create_file, open_file, close_file
-from nfs4_type import *
+from xdrdef.nfs4_type import *
import nfs4_ops as op
import nfs4lib
import threading
diff --git a/nfs4.1/server41tests/st_destroy_clientid.py b/nfs4.1/server41tests/st_destroy_clientid.py
index 1b193cf..6b7042f 100644
--- a/nfs4.1/server41tests/st_destroy_clientid.py
+++ b/nfs4.1/server41tests/st_destroy_clientid.py
@@ -1,5 +1,5 @@
from st_create_session import create_session
-from nfs4_const import *
+from xdrdef.nfs4_const import *
from environment import check, fail
import nfs4_ops as op
import nfs4lib
diff --git a/nfs4.1/server41tests/st_destroy_session.py b/nfs4.1/server41tests/st_destroy_session.py
index f4f0762..e3c3424 100644
--- a/nfs4.1/server41tests/st_destroy_session.py
+++ b/nfs4.1/server41tests/st_destroy_session.py
@@ -1,7 +1,7 @@
from st_create_session import create_session
-from nfs4_const import *
+from xdrdef.nfs4_const import *
from environment import check, checklist, fail, create_file, open_file
-from nfs4_type import open_owner4, openflag4, createhow4, open_claim4
+from xdrdef.nfs4_type import open_owner4, openflag4, createhow4, open_claim4
import nfs4_ops as op
import threading
import rpc
diff --git a/nfs4.1/server41tests/st_exchange_id.py b/nfs4.1/server41tests/st_exchange_id.py
index 956090f..39b8b0c 100644
--- a/nfs4.1/server41tests/st_exchange_id.py
+++ b/nfs4.1/server41tests/st_exchange_id.py
@@ -1,8 +1,8 @@
-from nfs4_const import *
+from xdrdef.nfs4_const import *
import nfs4_ops as op
import time
from environment import check, checklist, fail
-from nfs4_type import *
+from xdrdef.nfs4_type import *
from rpc import RPCAcceptError, GARBAGE_ARGS, RPCTimeout
from nfs4lib import NFS4Error, hash_oids, encrypt_oids

diff --git a/nfs4.1/server41tests/st_getdevicelist.py b/nfs4.1/server41tests/st_getdevicelist.py
index 7a10c6c..df0107d 100644
--- a/nfs4.1/server41tests/st_getdevicelist.py
+++ b/nfs4.1/server41tests/st_getdevicelist.py
@@ -1,5 +1,5 @@
-from nfs4_const import *
-from nfs4_type import *
+from xdrdef.nfs4_const import *
+from xdrdef.nfs4_type import *
from environment import check, fail, use_obj, open_file, create_file
import nfs4_ops as op
from block import Packer as BlockPacker, Unpacker as BlockUnpacker, \
diff --git a/nfs4.1/server41tests/st_lookup.py b/nfs4.1/server41tests/st_lookup.py
index 33e06b9..85ddcfe 100644
--- a/nfs4.1/server41tests/st_lookup.py
+++ b/nfs4.1/server41tests/st_lookup.py
@@ -1,4 +1,4 @@
-from nfs4_const import *
+from xdrdef.nfs4_const import *
from environment import check, fail
import nfs4_ops as op

diff --git a/nfs4.1/server41tests/st_lookupp.py b/nfs4.1/server41tests/st_lookupp.py
index 512ea6b..7aa7406 100644
--- a/nfs4.1/server41tests/st_lookupp.py
+++ b/nfs4.1/server41tests/st_lookupp.py
@@ -1,4 +1,4 @@
-from nfs4_const import *
+from xdrdef.nfs4_const import *
from environment import check, fail, use_obj
import nfs4_ops as op

diff --git a/nfs4.1/server41tests/st_open.py b/nfs4.1/server41tests/st_open.py
index 2ec646f..71e01fb 100644
--- a/nfs4.1/server41tests/st_open.py
+++ b/nfs4.1/server41tests/st_open.py
@@ -1,11 +1,11 @@
from st_create_session import create_session
-from nfs4_const import *
+from xdrdef.nfs4_const import *

from environment import check, checklist, fail, create_file, open_file, close_file
from environment import open_create_file_op
-from nfs4_type import open_owner4, openflag4, createhow4, open_claim4
-from nfs4_type import creatverfattr, fattr4, stateid4, locker4, lock_owner4
-from nfs4_type import open_to_lock_owner4
+from xdrdef.nfs4_type import open_owner4, openflag4, createhow4, open_claim4
+from xdrdef.nfs4_type import creatverfattr, fattr4, stateid4, locker4, lock_owner4
+from xdrdef.nfs4_type import open_to_lock_owner4
import nfs4_ops as op
import threading

diff --git a/nfs4.1/server41tests/st_putfh.py b/nfs4.1/server41tests/st_putfh.py
index d7bc0be..6d96048 100644
--- a/nfs4.1/server41tests/st_putfh.py
+++ b/nfs4.1/server41tests/st_putfh.py
@@ -1,4 +1,4 @@
-from nfs4_const import *
+from xdrdef.nfs4_const import *
from environment import check, fail, use_obj, create_confirm, close_file
import nfs4_ops as op

diff --git a/nfs4.1/server41tests/st_reboot.py b/nfs4.1/server41tests/st_reboot.py
index bbfc40e..b778fd7 100644
--- a/nfs4.1/server41tests/st_reboot.py
+++ b/nfs4.1/server41tests/st_reboot.py
@@ -1,5 +1,5 @@
-from nfs4_const import *
-from nfs4_type import *
+from xdrdef.nfs4_const import *
+from xdrdef.nfs4_type import *
from environment import check, checklist, fail, create_file, open_file, create_confirm
import sys
import os
diff --git a/nfs4.1/server41tests/st_reclaim_complete.py b/nfs4.1/server41tests/st_reclaim_complete.py
index f6baf09..1d9270f 100644
--- a/nfs4.1/server41tests/st_reclaim_complete.py
+++ b/nfs4.1/server41tests/st_reclaim_complete.py
@@ -1,5 +1,5 @@
from st_create_session import create_session
-from nfs4_const import *
+from xdrdef.nfs4_const import *
from environment import check, fail, open_file, create_file, create_confirm
import nfs4_ops as op
import nfs4lib
diff --git a/nfs4.1/server41tests/st_rename.py b/nfs4.1/server41tests/st_rename.py
index 943587c..51b6cd6 100644
--- a/nfs4.1/server41tests/st_rename.py
+++ b/nfs4.1/server41tests/st_rename.py
@@ -1,7 +1,7 @@
-from nfs4_const import *
+from xdrdef.nfs4_const import *
from environment import check, checklist, fail, maketree, rename_obj, get_invalid_utf8strings, create_obj, create_confirm, link, use_obj, create_file
import nfs4_ops as op
-from nfs4_type import *
+from xdrdef.nfs4_type import *

def testValidDir(t, env):
"""RENAME : normal operation
diff --git a/nfs4.1/server41tests/st_secinfo.py b/nfs4.1/server41tests/st_secinfo.py
index d9a1e98..b676edc 100644
--- a/nfs4.1/server41tests/st_secinfo.py
+++ b/nfs4.1/server41tests/st_secinfo.py
@@ -1,7 +1,7 @@
from st_create_session import create_session
-from nfs4_const import *
+from xdrdef.nfs4_const import *
from environment import check, fail, use_obj, bad_sessionid, create_file
-from nfs4_type import channel_attrs4
+from xdrdef.nfs4_type import channel_attrs4
import nfs4_ops as op
import nfs4lib

diff --git a/nfs4.1/server41tests/st_secinfo_no_name.py b/nfs4.1/server41tests/st_secinfo_no_name.py
index ada4853..2f8ee1b 100644
--- a/nfs4.1/server41tests/st_secinfo_no_name.py
+++ b/nfs4.1/server41tests/st_secinfo_no_name.py
@@ -1,7 +1,7 @@
from st_create_session import create_session
-from nfs4_const import *
+from xdrdef.nfs4_const import *
from environment import check, fail, bad_sessionid, create_file
-from nfs4_type import channel_attrs4
+from xdrdef.nfs4_type import channel_attrs4
import nfs4_ops as op
import nfs4lib

diff --git a/nfs4.1/server41tests/st_sequence.py b/nfs4.1/server41tests/st_sequence.py
index 96f5e42..e21bf7d 100644
--- a/nfs4.1/server41tests/st_sequence.py
+++ b/nfs4.1/server41tests/st_sequence.py
@@ -1,7 +1,7 @@
from st_create_session import create_session
-from nfs4_const import *
+from xdrdef.nfs4_const import *
from environment import check, fail, bad_sessionid, create_file
-from nfs4_type import channel_attrs4
+from xdrdef.nfs4_type import channel_attrs4
import nfs4_ops as op
import nfs4lib

diff --git a/nfs4.1/server41tests/st_trunking.py b/nfs4.1/server41tests/st_trunking.py
index b984425..142b924 100644
--- a/nfs4.1/server41tests/st_trunking.py
+++ b/nfs4.1/server41tests/st_trunking.py
@@ -1,7 +1,7 @@
-from nfs4_const import *
+from xdrdef.nfs4_const import *
import nfs4_ops as op
from environment import check, fail
-from nfs4_type import *
+from xdrdef.nfs4_type import *
import random
import nfs4lib
import threading
diff --git a/nfs4.1/server41tests/st_verify.py b/nfs4.1/server41tests/st_verify.py
index a1bc5ca..cfb3809 100644
--- a/nfs4.1/server41tests/st_verify.py
+++ b/nfs4.1/server41tests/st_verify.py
@@ -1,4 +1,4 @@
-from nfs4_const import *
+from xdrdef.nfs4_const import *
import nfs4_ops as op
from environment import check, checklist, get_invalid_clientid, makeStaleId, \
do_getattrdict, use_obj
diff --git a/nfs4.1/setup.py b/nfs4.1/setup.py
index e73a1d0..5c3a0df 100644
--- a/nfs4.1/setup.py
+++ b/nfs4.1/setup.py
@@ -31,22 +31,25 @@ class build_py(_build_py):
self.build_module(module, module_file, package)

def expand_xdr(self, dir):
+ print "expand = %r" % dir
cwd = os.getcwd()
- try:
- if dir:
- os.chdir(dir)
- xdr_files = glob(os.path.join(dir, "*.x"))
- for f in xdr_files:
- # Can conditionalize this
- # XXX need some way to pass options here
- xdrgen.run(f)
- try:
- os.remove("parser.out")
- os.remove("parsetab.py")
- except:
- print "Remove parse* failed"
- finally:
- os.chdir(cwd)
+ xdrdir = os.path.join(cwd, dir, 'xdrdef')
+ print "xdrdir = %r" % xdrdir
+ if os.path.exists(xdrdir):
+ try:
+ os.chdir(xdrdir)
+ xdr_files = glob(os.path.join(xdrdir, "*.x"))
+ for f in xdr_files:
+ # Can conditionalize this
+ # XXX need some way to pass options here
+ xdrgen.run(f)
+ try:
+ os.remove("parser.out")
+ os.remove("parsetab.py")
+ except:
+ print "Remove parse* failed"
+ finally:
+ os.chdir(cwd)

setup(name = "nfs4",
version = "0.0.0", # import this?
diff --git a/nfs4.1/testclient.py b/nfs4.1/testclient.py
index 9189c60..95e90e1 100755
--- a/nfs4.1/testclient.py
+++ b/nfs4.1/testclient.py
@@ -193,7 +193,7 @@ def run_filter(test, options):

def printflags(list):
"""Print all legal flag names, which are given in list"""
- from nfs4_const import nfs_opnum4
+ from xdrdef.nfs4_const import nfs_opnum4
command_names = [s.lower()[3:].replace('_', '') \
for s in nfs_opnum4.values()]
list.sort()
diff --git a/nfs4.1/testserver.py b/nfs4.1/testserver.py
index 61e308c..7c10fe6 100755
--- a/nfs4.1/testserver.py
+++ b/nfs4.1/testserver.py
@@ -190,7 +190,7 @@ def run_filter(test, options):

def printflags(list):
"""Print all legal flag names, which are given in list"""
- from nfs4_const import nfs_opnum4
+ from xdrdef.nfs4_const import nfs_opnum4
command_names = [s.lower()[3:].replace('_', '') \
for s in nfs_opnum4.values()]
list.sort()
diff --git a/nfs4.1/xdrdef/__init__.py b/nfs4.1/xdrdef/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/nfs4.1/nfs4.x b/nfs4.1/xdrdef/nfs4.x
similarity index 100%
rename from nfs4.1/nfs4.x
rename to nfs4.1/xdrdef/nfs4.x
diff --git a/nfs4.1/nfs4.x.diff b/nfs4.1/xdrdef/nfs4.x.diff
similarity index 100%
rename from nfs4.1/nfs4.x.diff
rename to nfs4.1/xdrdef/nfs4.x.diff
diff --git a/nfs4.1/pnfs_block.x b/nfs4.1/xdrdef/pnfs_block.x
similarity index 100%
rename from nfs4.1/pnfs_block.x
rename to nfs4.1/xdrdef/pnfs_block.x
diff --git a/nfs4.1/sctrl.x b/nfs4.1/xdrdef/sctrl.x
similarity index 100%
rename from nfs4.1/sctrl.x
rename to nfs4.1/xdrdef/sctrl.x
--
1.8.5.2 (Apple Git-48)


2014-06-09 21:25:58

by J. Bruce Fields

[permalink] [raw]
Subject: Re: [PATCH pynfs v2 00/16] prep for flex file layout server

On Thu, Jun 05, 2014 at 09:55:28AM -0400, Weston Andros Adamson wrote:
> Changes in v2:
>
> - moved "4.1 client: reclaim_complete after create_session" to
> "dataserver: reclaim_complete after create_session" as the implicit
> reclaim complete is needed in DS path, but not in all server tests.
>
> - dropped "4.1 server: service RECLAIM_COMPLETE operations" as it's
> unneeded.
>
> - formatted these patches with -M flag so we can see moved files
>
> .. and I pushed the changes to my ff_prep branch.

Thanks for the patches! Applied, checked that they didn't break
anything for me, and pushed out.

(The only thing I noticed was that I had to rebuild things, to account
for the renamed files.)

--b.

>
> Thanks!
> -dros
>
>
> These patches are in preparation for the pynfs implementation of a flex
> file layout server.
>
> I already have patches for a working flex file server, but I figure those
> should wait until the spec is complete ;)
>
> I pushed these patches to my linux-nfs.org tree on branch 'ff_prep':
>
> git://git.linux-nfs.org/projects/dros/pynfs.git
>
> The prep includes:
>
> - patches that enable pynfs mds using real v4.1 DSes (on the backend,
> not usable from clients as there is no stateid sharing between mds and ds)
>
> - fix several bugs in pnfs path
>
> - move .x files to subdir 'xdrdef' - the nfs4.1 directory was getting crowded
> and we're going to add several more .x files along with all of the
> autogenerated files. Note this change touches server tests too.
>
> - clean up the nfs4server's output - no longer print out EVERY part of EVERY
> operation which was very efficient at hiding tracebacks and made pynfs
> even slower. Old functionality is now switched on with -v flag. Also
> added an in-between mode "-s" that prints a summary of whats going on.
>
> - support for NFSv3 backend communication - this is not actually used yet,
> but can be tested with file layout by always returning
> NFS4ERR_LAYOUTUNAVAILABLE in layoutget and using DataServer3 class instead
> of DataServer41
>
>
> Weston Andros Adamson (16):
> dataserver: reclaim_complete after create_session
> dataserver: only catch connection error
> 4.1 server: avoid traceback in DS disconnect()
> move .x files to subdir 'xdrdef'
> 4.1 client: remove unused imports
> 4.1 server: add -v flag & silence random output
> 4.1 server: add -s option to print summary of ops
> dataserver: make generic interface to ops
> dataserver: don't import * from nfs4 specific mods
> 4.1 server: move nfs4_ops.py to nfs_ops.py
> add mntv3, portmapv2 and nfsv3 .x files
> dataserver: separate generic and 4.1 code
> 4.1 server: add support for NFSv3 data servers
> 4.1 server: get rid of old op_getdeviceinfo
> rpc: on socket error, close and mark pipe inactive
> nfs3clnt: reconnect when sending on inactive pipe
>
> nfs4.1/block.py | 8 +-
> nfs4.1/client41tests/environment.py | 4 +-
> nfs4.1/config.py | 8 +-
> nfs4.1/dataserver.py | 308 ++++++++---
> nfs4.1/fs.py | 38 +-
> nfs4.1/nfs3client.py | 185 +++++++
> nfs4.1/nfs4_ops.py | 61 ---
> nfs4.1/nfs4client.py | 47 +-
> nfs4.1/nfs4commoncode.py | 10 +-
> nfs4.1/nfs4lib.py | 62 ++-
> nfs4.1/nfs4server.py | 163 +++---
> nfs4.1/nfs4state.py | 15 +-
> nfs4.1/nfs_ops.py | 89 +++
> nfs4.1/server41tests/environment.py | 4 +-
> nfs4.1/server41tests/st_block.py | 4 +-
> nfs4.1/server41tests/st_compound.py | 4 +-
> nfs4.1/server41tests/st_create_session.py | 4 +-
> nfs4.1/server41tests/st_current_stateid.py | 8 +-
> nfs4.1/server41tests/st_debug.py | 4 +-
> nfs4.1/server41tests/st_delegation.py | 4 +-
> nfs4.1/server41tests/st_destroy_clientid.py | 2 +-
> nfs4.1/server41tests/st_destroy_session.py | 4 +-
> nfs4.1/server41tests/st_exchange_id.py | 4 +-
> nfs4.1/server41tests/st_getdevicelist.py | 4 +-
> nfs4.1/server41tests/st_lookup.py | 2 +-
> nfs4.1/server41tests/st_lookupp.py | 2 +-
> nfs4.1/server41tests/st_open.py | 8 +-
> nfs4.1/server41tests/st_putfh.py | 2 +-
> nfs4.1/server41tests/st_reboot.py | 4 +-
> nfs4.1/server41tests/st_reclaim_complete.py | 2 +-
> nfs4.1/server41tests/st_rename.py | 4 +-
> nfs4.1/server41tests/st_secinfo.py | 4 +-
> nfs4.1/server41tests/st_secinfo_no_name.py | 4 +-
> nfs4.1/server41tests/st_sequence.py | 4 +-
> nfs4.1/server41tests/st_trunking.py | 4 +-
> nfs4.1/server41tests/st_verify.py | 2 +-
> nfs4.1/server_exports.py | 7 +-
> nfs4.1/setup.py | 33 +-
> nfs4.1/testclient.py | 2 +-
> nfs4.1/testserver.py | 2 +-
> nfs4.1/xdrdef/__init__.py | 0
> nfs4.1/xdrdef/mnt3.x | 68 +++
> nfs4.1/xdrdef/nfs3.x | 818 ++++++++++++++++++++++++++++
> nfs4.1/{ => xdrdef}/nfs4.x | 0
> nfs4.1/{ => xdrdef}/nfs4.x.diff | 0
> nfs4.1/{ => xdrdef}/pnfs_block.x | 0
> nfs4.1/xdrdef/portmap.x | 51 ++
> nfs4.1/{ => xdrdef}/sctrl.x | 0
> rpc/rpc.py | 26 +-
> 49 files changed, 1704 insertions(+), 389 deletions(-)
> create mode 100644 nfs4.1/nfs3client.py
> delete mode 100644 nfs4.1/nfs4_ops.py
> create mode 100644 nfs4.1/nfs_ops.py
> create mode 100644 nfs4.1/xdrdef/__init__.py
> create mode 100644 nfs4.1/xdrdef/mnt3.x
> create mode 100644 nfs4.1/xdrdef/nfs3.x
> rename nfs4.1/{ => xdrdef}/nfs4.x (100%)
> rename nfs4.1/{ => xdrdef}/nfs4.x.diff (100%)
> rename nfs4.1/{ => xdrdef}/pnfs_block.x (100%)
> create mode 100644 nfs4.1/xdrdef/portmap.x
> rename nfs4.1/{ => xdrdef}/sctrl.x (100%)
>
> --
> 1.8.5.2 (Apple Git-48)
>

2014-06-05 13:55:50

by Weston Andros Adamson

[permalink] [raw]
Subject: [PATCH pynfs v2 01/16] dataserver: reclaim_complete after create_session

Send RECLAIM_COMPLETE after CREATE_SESSION. This enables backend
communication to v4.1 linux nfsd servers (i/o through MDS only).

Signed-off-by: Weston Andros Adamson <[email protected]>
---
nfs4.1/dataserver.py | 1 +
1 file changed, 1 insertion(+)

diff --git a/nfs4.1/dataserver.py b/nfs4.1/dataserver.py
index 65e4f55..ade55e1 100644
--- a/nfs4.1/dataserver.py
+++ b/nfs4.1/dataserver.py
@@ -54,6 +54,7 @@ class DataServer(object):
# as wide as the client/MDS channel (at least for linux client)
fore_attrs = channel_attrs4(0, 16384, 16384, 2868, 8, 8, [])
self.sess = c.create_session(fore_attrs=fore_attrs)
+ sess.compound([op.reclaim_complete(FALSE)])
self.make_root()

def disconnect(self):
--
1.8.5.2 (Apple Git-48)


2014-06-05 13:55:56

by Weston Andros Adamson

[permalink] [raw]
Subject: [PATCH pynfs v2 07/16] 4.1 server: add -s option to print summary of ops

As a middle ground between verbose (-v) mode and silent mode, add
"-s" (aka "--show_summary") to print one line per operation.

The summary mode will print a "role" header whenever the role changes.

Example output - mds starts, talks to v3 ds (.200), client (.11) mounts,
touches an existing file:

call v3 172.16.200.200:2049
access
Mounting (2, 6) on '/files'

handle v4.1 ::ffff:172.16.200.11:758
exchange_id
create_session
sequence, reclaim_complete
sequence, putrootfh, secinfo_no_name
sequence, putrootfh, getfh, getattr
sequence, putfh, getattr
(repeated 6 times)
sequence, putfh, access, getattr
sequence, putfh, lookup, getfh, getattr
(repeated 1 times)
sequence, putfh, secinfo -> NFS4ERR_NOTSUPP
sequence, putfh, getattr
(repeated 4 times)
sequence, putfh, access, getattr

call v3 172.16.200.200:2049
create -> NFS3ERR_EXIST
lookup
getattr
(repeated 1 times)

handle v4.1 ::ffff:172.16.200.11:758
sequence, putfh, open, getfh, access, getattr

call v3 172.16.200.200:2049
getattr
(repeated 1 times)

handle v4.1 ::ffff:172.16.200.11:758
sequence, putfh, setattr, getattr
sequence, putfh, close, getattr

Signed-off-by: Weston Andros Adamson <[email protected]>
---
nfs4.1/dataserver.py | 16 ++++++++++------
nfs4.1/nfs4client.py | 7 ++++++-
nfs4.1/nfs4server.py | 47 ++++++++++++++++++++++++++++++++++++++++++++++-
nfs4.1/server_exports.py | 7 ++++---
4 files changed, 66 insertions(+), 11 deletions(-)

diff --git a/nfs4.1/dataserver.py b/nfs4.1/dataserver.py
index c400d22..dd81b20 100644
--- a/nfs4.1/dataserver.py
+++ b/nfs4.1/dataserver.py
@@ -13,8 +13,8 @@ import socket

log = logging.getLogger("Dataserver Manager")

-class DataServer(object):
- def __init__(self, server, port, path, flavor=rpc.AUTH_SYS, active=True, mdsds=True, multipath_servers=None):
+class DataServer41(object):
+ def __init__(self, server, port, path, flavor=rpc.AUTH_SYS, active=True, mdsds=True, multipath_servers=None, summary=None):
self.mdsds = mdsds
self.server = server
self.port = int(port)
@@ -32,6 +32,8 @@ class DataServer(object):
else:
self.multipath_servers = []

+ self.summary = summary
+
if active:
self.up()

@@ -47,7 +49,8 @@ class DataServer(object):
# only support root with AUTH_SYS for now
s1 = rpc.security.instance(rpc.AUTH_SYS)
self.cred1 = s1.init_cred(uid=0, gid=0)
- self.c1 = nfs4client.NFS4Client(self.server, self.port)
+ self.c1 = nfs4client.NFS4Client(self.server, self.port,
+ summary=self.summary)
self.c1.set_cred(self.cred1)
self.c1.null()
c = self.c1.new_client("DS.init_%s" % self.server)
@@ -173,7 +176,7 @@ class DSDevice(object):
self.address_body = None # set by load()
self.mdsds = mdsds # if you are both the DS and the MDS we are the only server

- def load(self, filename):
+ def load(self, filename, server_obj):
""" Read dataservers from configuration file:
where each line has format e.g. server[:[port][/path]]
"""
@@ -195,8 +198,9 @@ class DSDevice(object):
try:
log.info("Adding dataserver ip:%s port:%s path:%s" %
(server, port, '/'.join(path)))
- ds = DataServer(server, port, path, mdsds=self.mdsds,
- multipath_servers=server_list)
+ ds = DataServer41(server, port, path, mdsds=self.mdsds,
+ multipath_servers=server_list,
+ summary=server_obj.summary)
self.list.append(ds)
except socket.error:
log.critical("cannot access %s:%i/%s" %
diff --git a/nfs4.1/nfs4client.py b/nfs4.1/nfs4client.py
index 0ba84bd..4ae884a 100644
--- a/nfs4.1/nfs4client.py
+++ b/nfs4.1/nfs4client.py
@@ -21,7 +21,7 @@ logging.basicConfig(level=logging.INFO,
log_cb = logging.getLogger("nfs.client.cb")

class NFS4Client(rpc.Client, rpc.Server):
- def __init__(self, host='localhost', port=2049, minorversion=1, ctrl_proc=16):
+ def __init__(self, host='localhost', port=2049, minorversion=1, ctrl_proc=16, summary=None):
rpc.Client.__init__(self, 100003, 4)
self.prog = 0x40000000
self.versions = [1] # List of supported versions of prog
@@ -36,6 +36,7 @@ class NFS4Client(rpc.Client, rpc.Server):
self.c1 = self.connect(self.server_address)
self.sessions = {} # XXX Really, this should be per server
self.ctrl_proc = ctrl_proc
+ self.summary = summary

def set_cred(self, credinfo):
self.default_cred = credinfo
@@ -83,6 +84,10 @@ class NFS4Client(rpc.Client, rpc.Server):
pipe = kwargs.get("pipe", None)
res = self.listen(xid, pipe=pipe)
log_cb.info("compound result = %r" % (res,))
+ if self.summary:
+ self.summary.show_op('call v4.1 %s:%s' % self.server_address,
+ [ nfs_opnum4[a.argop].lower()[3:] for a in args[0] ],
+ nfsstat4[res.status])
return res

def listen(self, xid, pipe=None, timeout=10.0):
diff --git a/nfs4.1/nfs4server.py b/nfs4.1/nfs4server.py
index a495d3c..3d2d4cf 100755
--- a/nfs4.1/nfs4server.py
+++ b/nfs4.1/nfs4server.py
@@ -502,6 +502,41 @@ class Slot(object):

# STUB - for client, need to track slot usage

+class SummaryOutput:
+ def __init__(self, enabled=True):
+ self._enabled = enabled
+ self._last = None
+ self._last_role = None
+ self._repeat_count = 0
+
+ def show_op(self, role, opnames, status):
+ if not self._enabled:
+ return
+
+ summary_line = " %s" % ', '.join(opnames)
+
+ if status != "NFS4_OK" and status != "NFS3_OK":
+ summary_line += " -> %s" % (status,)
+
+ print_summary_line = True
+ if summary_line != self._last or role != self._last_role:
+ if self._last and self._repeat_count:
+ print " (repeated %u times)" % self._repeat_count
+ self._last = summary_line
+ self._repeat_count = 0
+ else:
+ print_summary_line = False
+ self._repeat_count += 1
+
+ if self._last_role != role:
+ print
+ print role
+ self._last_role = role
+
+ if print_summary_line:
+ print summary_line
+
+
##################################################
# The primary class - it is excessively long #
##################################################
@@ -527,6 +562,8 @@ class NFS4Server(rpc.Server):
log_41.setLevel(9)
log_cfg.setLevel(20)

+ self.summary = SummaryOutput(kwargs.pop('show_summary', False))
+
rpc.Server.__init__(self, prog=NFS4_PROGRAM, versions=[4], port=port,
**kwargs)
self.root = RootFS().root # Root of exported filesystem tree
@@ -776,6 +813,7 @@ class NFS4Server(rpc.Server):
return env
# Handle the individual operations
status = NFS4_OK
+ opnames = []
for arg in args.argarray:
opname = nfs_opnum4.get(arg.argop, 'op_illegal')
log_41.info("*** %s (%d) ***" % (opname, arg.argop))
@@ -805,10 +843,14 @@ class NFS4Server(rpc.Server):
result = encode_status_by_name(opname.lower()[3:],
NFS4ERR_SERVERFAULT)
env.results.append(result)
+ opnames.append(opname.lower()[3:])
status = result.status
if status != NFS4_OK:
break
log_41.info("Replying. Status %s (%d)" % (nfsstat4[status], status))
+ client_addr = '%s:%s' % cred.connection._s.getpeername()[:2]
+ self.summary.show_op('handle v4.1 %s' % client_addr,
+ opnames, nfsstat4[status])
return env

def delete_session(self, session, sessionid):
@@ -2059,6 +2101,8 @@ def scan_options():
help="Reset and clear any disk-based filesystems")
p.add_option("-v", "--verbose", action="store_true", default=False,
help="Print debug info to screen and enter interpreter on ^C")
+ p.add_option("-s", "--show_summary", action="store_true", default=False,
+ help="Print short summary of operations")
p.add_option("--use_block", action="store_true", default=False,
help="Mount a block-pnfs fs")
p.add_option("--use_files", action="store_true", default=False,
@@ -2092,7 +2136,8 @@ if __name__ == "__main__":
S = NFS4Server(port=opts.port,
is_mds=opts.use_block or opts.use_files,
is_ds = opts.is_ds,
- verbose = opts.verbose)
+ verbose = opts.verbose,
+ show_summary = opts.show_summary)
read_exports(S, opts)
if True:
S.start()
diff --git a/nfs4.1/server_exports.py b/nfs4.1/server_exports.py
index d96b27b..ef857ee 100644
--- a/nfs4.1/server_exports.py
+++ b/nfs4.1/server_exports.py
@@ -15,7 +15,7 @@ def mount_stuff(server, opts):
E = BlockLayoutFS(5, backing_device=dev)
server.mount(E, path="/block")
if opts.use_files:
- dservers = _load_dataservers(opts.dataservers, server.is_ds and server.is_mds)
+ dservers = _load_dataservers(opts.dataservers, server)
if dservers is None:
return
F = FileLayoutFS(6, dservers)
@@ -33,7 +33,8 @@ def _create_simple_block_dev():
c1 = Concat([s3, s1])
return BlockVolume(c1)

-def _load_dataservers(file, connect_to_ds=False):
+def _load_dataservers(filename, server):
+ connect_to_ds = server.is_ds and server.is_mds
dss = DSDevice(connect_to_ds)
- dss.load(file)
+ dss.load(filename, server)
return dss;
--
1.8.5.2 (Apple Git-48)


2014-06-05 13:56:01

by Weston Andros Adamson

[permalink] [raw]
Subject: [PATCH pynfs v2 13/16] 4.1 server: add support for NFSv3 data servers

Add the NFSv3 client and a new DataServer class that handles DS ops
using the v3 client.

DataServer3 is not used yet, as it requires flexfile layouts in order
to pass a v3 DS to clients.

Tested with linux client mounting pnfs MDS via v4.1 (disabling pnfs)
and a linux server acting as the v3 DS.

Signed-off-by: Weston Andros Adamson <[email protected]>
---
nfs4.1/dataserver.py | 100 ++++++++++++++++++++++++++++
nfs4.1/nfs3client.py | 180 +++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 280 insertions(+)
create mode 100644 nfs4.1/nfs3client.py

diff --git a/nfs4.1/dataserver.py b/nfs4.1/dataserver.py
index 5c604dc..f32f3d7 100644
--- a/nfs4.1/dataserver.py
+++ b/nfs4.1/dataserver.py
@@ -3,9 +3,12 @@ import nfs4lib
import xdrdef.nfs4_type as type4
from xdrdef.nfs4_pack import NFS4Packer
import xdrdef.nfs4_const as const4
+import xdrdef.nfs3_type as type3
+import xdrdef.nfs3_const as const3
import time
import logging
import nfs4client
+import nfs3client
import hashlib
import sys
import nfs_ops
@@ -14,6 +17,7 @@ import socket
log = logging.getLogger("Dataserver Manager")

op4 = nfs_ops.NFS4ops()
+op3 = nfs_ops.NFS3ops()

class DataServer(object):
def __init__(self, server, port, path, flavor=rpc.AUTH_SYS, active=True, mdsds=True, multipath_servers=None, summary=None):
@@ -207,6 +211,102 @@ class DataServer41(DataServer):
attrdict = res.resarray[-1].obj_attributes
return attrdict.get(const4.FATTR4_SIZE, 0)

+class DataServer3(DataServer):
+ def _execute(self, procnum, procarg, exceptions=(), delay=5, maxretries=3):
+ """ execute the NFS call
+ If an error code is specified in the exceptions it means that the
+ caller wants to handle the error himself
+ """
+ retry_errors = []
+ while True:
+ res = self.c1.proc(procnum, procarg)
+ if res.status == const3.NFS3_OK or res.status in exceptions:
+ return res
+ elif res.status in retry_errors:
+ if maxretries > 0:
+ maxretries -= 1
+ time.sleep(delay)
+ else:
+ log.error("Too many retries with DS %s" % self.server)
+ raise Exception("Dataserver communication retry error")
+ else:
+ log.error("Unhandled status %s from DS %s" %
+ (const3.nfsstat3[res.status], self.server))
+ raise Exception("Dataserver communication error")
+
+ def connect(self):
+ # only support root with AUTH_SYS for now
+ s1 = rpc.security.instance(rpc.AUTH_SYS)
+ self.cred1 = s1.init_cred(uid=0, gid=0)
+ self.c1 = nfs3client.NFS3Client(self.server, self.port,
+ summary=self.summary)
+ self.c1.set_cred(self.cred1)
+ self.rootfh = type3.nfs_fh3(self.c1.mntclnt.get_rootfh(self.path))
+ self.c1.null()
+
+ def make_root(self):
+ """ don't actually make a root path - we must use it as the export """
+ need = const3.ACCESS3_READ | const3.ACCESS3_LOOKUP | \
+ const3.ACCESS3_MODIFY | const3.ACCESS3_EXTEND
+ arg = op3.access(self.rootfh, need)
+ res = self._execute(const3.NFSPROC3_ACCESS, arg)
+ if res.resok.access != need:
+ raise RuntimeError
+ # XXX clean DS directory
+
+ def open_file(self, mds_fh):
+ name = self.fh_to_name(mds_fh)
+ where = type3.diropargs3(self.rootfh, name)
+ attr = type3.sattr3(mode=type3.set_mode3(True, 0777),
+ uid=type3.set_uid3(True, 0),
+ gid=type3.set_gid3(True, 0),
+ size=type3.set_size3(False),
+ atime=type3.set_atime(False),
+ mtime=type3.set_mtime(False))
+ how = type3.createhow3(const3.GUARDED, attr)
+ arg = op3.create(where, how)
+ res = self._execute(const3.NFSPROC3_CREATE, arg,
+ exceptions=(const3.NFS3ERR_EXIST,))
+
+ if res.status == const3.NFS3_OK:
+ self.filehandles[mds_fh] = (res.resok.obj.handle, None)
+
+ else:
+ arg = op3.lookup(type3.diropargs3(self.rootfh, name))
+ res = self._execute(const3.NFSPROC3_LOOKUP, arg)
+
+ self.filehandles[mds_fh] = (res.resok.object, None)
+
+ def close_file(self, mds_fh):
+ del self.filehandles[mds_fh]
+
+ def read(self, fh, pos, count):
+ arg = op3.read(fh, pos, count)
+ res = self._execute(const3.NFSPROC3_READ, arg)
+ # XXX check res.status?
+ return res.resok.data
+
+ def write(self, fh, pos, data):
+ arg = op3.write(fh, pos, len(data), const3.FILE_SYNC, data)
+ # There are all sorts of error handling issues here
+ res = self._execute(const3.NFSPROC3_WRITE, arg)
+
+ def truncate(self, fh, size):
+ attr = type3.sattr3(mode=type3.set_mode3(False),
+ uid=type3.set_uid3(False),
+ gid=type3.set_gid3(False),
+ size=type3.set_size3(True, size),
+ atime=type3.set_atime(False),
+ mtime=type3.set_mtime(False))
+ arg = op3.setattr(fh, attr, type3.sattrguard3(check=False))
+ res = self._execute(const3.NFSPROC3_SETATTR, arg)
+
+ def get_size(self, fh):
+ arg = op3.getattr(fh)
+ res = self._execute(const3.NFSPROC3_GETATTR, arg)
+ # XXX check res.status?
+ return res.resok.obj_attributes.size
+

class DSDevice(object):
def __init__(self, mdsds):
diff --git a/nfs4.1/nfs3client.py b/nfs4.1/nfs3client.py
new file mode 100644
index 0000000..79a6f0e
--- /dev/null
+++ b/nfs4.1/nfs3client.py
@@ -0,0 +1,180 @@
+import use_local # HACK so don't have to rebuild constantly
+import rpc
+import nfs4lib
+#from nfs4lib import NFS4Error, NFS4Replay, inc_u32
+from xdrdef.sctrl_pack import SCTRLPacker, SCTRLUnpacker
+from xdrdef.nfs3_type import *
+from xdrdef.nfs3_const import *
+from xdrdef.nfs3_pack import NFS3Packer, NFS3Unpacker
+from xdrdef.mnt3_type import *
+from xdrdef.mnt3_const import *
+from xdrdef.mnt3_pack import MNT3Packer, MNT3Unpacker
+from xdrdef.portmap_type import *
+from xdrdef.portmap_const import *
+from xdrdef.portmap_pack import PORTMAPPacker, PORTMAPUnpacker
+import nfs_ops
+import time, struct
+import threading
+import hmac
+import os.path
+
+import traceback
+import logging
+logging.basicConfig(level=logging.INFO,
+ format="%(levelname)-7s:%(name)s:%(message)s")
+log_cb = logging.getLogger("nfs.client.cb")
+
+op3 = nfs_ops.NFS3ops()
+
+class PORTMAPClient(rpc.Client):
+ def __init__(self, host='localhost', port=PMAP_PORT):
+ rpc.Client.__init__(self, PMAP_PROG, PMAP_VERS)
+ self.server_address = (host, port)
+ self.c1 = self.connect(self.server_address)
+
+ def proc_async(self, procnum, procarg, credinfo=None, pipe=None,
+ checks=True, packer=PORTMAPPacker):
+ if credinfo is None:
+ credinfo = self.default_cred
+ if pipe is None:
+ pipe = self.c1
+ p = packer(check_enum=checks, check_array=checks)
+ arg_packer = getattr(p, 'pack_%s' % procarg.__class__.__name__)
+ arg_packer(procarg)
+ return self.send_call(pipe, procnum, p.get_buffer(), credinfo)
+
+ def proc(self, procnum, procarg, restypename, **kwargs):
+ xid = self.proc_async(procnum, procarg, **kwargs)
+ pipe = kwargs.get("pipe", None)
+ res = self.listen(xid, restypename, pipe=pipe)
+ return res
+
+ def listen(self, xid, restypename, pipe=None, timeout=10.0):
+ if pipe is None:
+ pipe = self.c1
+ header, data = pipe.listen(xid, timeout)
+ if data:
+ p = PORTMAPUnpacker(data)
+ res_unpacker = getattr(p, 'unpack_%s' % restypename)
+ data = res_unpacker()
+ return data
+
+ def get_port(self, prog, vers):
+ arg = mapping(prog, vers, IPPROTO_TCP, 0)
+
+ res = self.proc(PMAPPROC_GETPORT, arg, 'uint')
+ return res
+
+class Mnt3Client(rpc.Client):
+ def __init__(self, host='localhost', port=None):
+ rpc.Client.__init__(self, MOUNT_PROGRAM, MOUNT_V3)
+ self.server_address = (host, port)
+ self.c1 = self.connect(self.server_address)
+
+ def proc_async(self, procnum, procarg, credinfo=None, pipe=None,
+ checks=True, packer=MNT3Packer):
+ if credinfo is None:
+ credinfo = self.default_cred
+ if pipe is None:
+ pipe = self.c1
+ p = packer(check_enum=checks, check_array=checks)
+ arg_packer = getattr(p, 'pack_%s' % procarg.__class__.__name__)
+ arg_packer(procarg)
+ return self.send_call(pipe, procnum, p.get_buffer(), credinfo)
+
+ def proc(self, procnum, procarg, restypename, **kwargs):
+ xid = self.proc_async(procnum, procarg, **kwargs)
+ pipe = kwargs.get("pipe", None)
+ res = self.listen(xid, restypename, pipe=pipe)
+ return res
+
+ def listen(self, xid, restypename, pipe=None, timeout=10.0):
+ if pipe is None:
+ pipe = self.c1
+ header, data = pipe.listen(xid, timeout)
+ if data:
+ p = MNT3Unpacker(data)
+ res_unpacker = getattr(p, 'unpack_%s' % restypename)
+ data = res_unpacker()
+ return data
+
+ def get_rootfh(self, export):
+
+ class dirpath(str):
+ pass
+
+ arg = dirpath('/' + os.path.join(*export))
+ res = self.proc(MOUNTPROC3_MNT, arg, 'mountres3')
+ return res.mountinfo.fhandle
+
+class NFS3Client(rpc.Client):
+ def __init__(self, host='localhost', port=None, ctrl_proc=16, summary=None):
+ rpc.Client.__init__(self, 100003, 3)
+ #self.prog = 0x40000000
+ #self.versions = [1] # List of supported versions of prog
+
+ #self.minorversion = minorversion
+ #self.minor_versions = [minorversion]
+ #self.tag = "default tag"
+ #self.impl_id = nfs_impl_id4("citi.umich.edu", "pynfs X.X",
+ # nfs4lib.get_nfstime())
+
+ self.portmap = PORTMAPClient(host=host)
+ self.mntport = self.portmap.get_port(MOUNT_PROGRAM, MOUNT_V3)
+ if not port:
+ self.port = self.portmap.get_port(100003, 3)
+ else:
+ self.port = port
+
+ self.verifier = struct.pack('>d', time.time())
+ self.server_address = (host, self.port)
+ self.c1 = self.connect(self.server_address)
+ #self.sessions = {} # XXX Really, this should be per server
+ self.ctrl_proc = ctrl_proc
+ self.summary = summary
+ self.mntclnt = Mnt3Client(host=host, port=self.mntport)
+
+ def set_cred(self, credinfo):
+ self.default_cred = credinfo
+
+ def null_async(self, data=""):
+ return self.send_call(self.c1, 0, data)
+
+ def null(self, *args, **kwargs):
+ xid = self.null_async(*args, **kwargs)
+ return self.listen(xid)
+
+ def proc_async(self, procnum, procarg, credinfo=None, pipe=None,
+ checks=True, packer=NFS3Packer):
+ if credinfo is None:
+ credinfo = self.default_cred
+ if pipe is None:
+ pipe = self.c1
+ p = packer(check_enum=checks, check_array=checks)
+ arg_packer = getattr(p, 'pack_%s' % procarg.__class__.__name__)
+ arg_packer(procarg)
+ return self.send_call(pipe, procnum, p.get_buffer(), credinfo)
+
+ def proc(self, procnum, procarg, **kwargs):
+ xid = self.proc_async(procnum, procarg, **kwargs)
+ pipe = kwargs.get("pipe", None)
+ res = self.listen(xid, procarg=procarg, pipe=pipe)
+ if self.summary:
+ self.summary.show_op('call v3 %s:%s' % self.server_address,
+ [ procarg.__class__.__name__.lower()[:-1 * len('3args')] ],
+ nfsstat3[res.status])
+ return res
+
+ def listen(self, xid, procarg=None, pipe=None, timeout=10.0):
+ if pipe is None:
+ pipe = self.c1
+ header, data = pipe.listen(xid, timeout)
+ if data:
+ p = NFS3Unpacker(data)
+ argname = procarg.__class__.__name__
+ # FOO3args -> FOO3res
+ resname = argname[:-4] + 'res'
+ res_unpacker = getattr(p, 'unpack_%s' % resname)
+ data = res_unpacker()
+ return data
+
--
1.8.5.2 (Apple Git-48)


2014-06-05 14:19:18

by J. Bruce Fields

[permalink] [raw]
Subject: Re: [PATCH pynfs v2 00/16] prep for flex file layout server

On Thu, Jun 05, 2014 at 09:55:28AM -0400, Weston Andros Adamson wrote:
> Changes in v2:
>
> - moved "4.1 client: reclaim_complete after create_session" to
> "dataserver: reclaim_complete after create_session" as the implicit
> reclaim complete is needed in DS path, but not in all server tests.
>
> - dropped "4.1 server: service RECLAIM_COMPLETE operations" as it's
> unneeded.
>
> - formatted these patches with -M flag so we can see moved files
>
> .. and I pushed the changes to my ff_prep branch.
>
> Thanks!
> -dros
>
>
> These patches are in preparation for the pynfs implementation of a flex
> file layout server.
>
> I already have patches for a working flex file server, but I figure those
> should wait until the spec is complete ;)
>
> I pushed these patches to my linux-nfs.org tree on branch 'ff_prep':
>
> git://git.linux-nfs.org/projects/dros/pynfs.git

$ git pull git://git.linux-nfs.org/projects/dros/pynfs.git ff_prep

fatal: remote error: access denied or repository not exported:
/projects/dros/pynfs.git

No big deal, just using git-am instead.....

--b.

>
> The prep includes:
>
> - patches that enable pynfs mds using real v4.1 DSes (on the backend,
> not usable from clients as there is no stateid sharing between mds and ds)
>
> - fix several bugs in pnfs path
>
> - move .x files to subdir 'xdrdef' - the nfs4.1 directory was getting crowded
> and we're going to add several more .x files along with all of the
> autogenerated files. Note this change touches server tests too.
>
> - clean up the nfs4server's output - no longer print out EVERY part of EVERY
> operation which was very efficient at hiding tracebacks and made pynfs
> even slower. Old functionality is now switched on with -v flag. Also
> added an in-between mode "-s" that prints a summary of whats going on.
>
> - support for NFSv3 backend communication - this is not actually used yet,
> but can be tested with file layout by always returning
> NFS4ERR_LAYOUTUNAVAILABLE in layoutget and using DataServer3 class instead
> of DataServer41
>
>
> Weston Andros Adamson (16):
> dataserver: reclaim_complete after create_session
> dataserver: only catch connection error
> 4.1 server: avoid traceback in DS disconnect()
> move .x files to subdir 'xdrdef'
> 4.1 client: remove unused imports
> 4.1 server: add -v flag & silence random output
> 4.1 server: add -s option to print summary of ops
> dataserver: make generic interface to ops
> dataserver: don't import * from nfs4 specific mods
> 4.1 server: move nfs4_ops.py to nfs_ops.py
> add mntv3, portmapv2 and nfsv3 .x files
> dataserver: separate generic and 4.1 code
> 4.1 server: add support for NFSv3 data servers
> 4.1 server: get rid of old op_getdeviceinfo
> rpc: on socket error, close and mark pipe inactive
> nfs3clnt: reconnect when sending on inactive pipe
>
> nfs4.1/block.py | 8 +-
> nfs4.1/client41tests/environment.py | 4 +-
> nfs4.1/config.py | 8 +-
> nfs4.1/dataserver.py | 308 ++++++++---
> nfs4.1/fs.py | 38 +-
> nfs4.1/nfs3client.py | 185 +++++++
> nfs4.1/nfs4_ops.py | 61 ---
> nfs4.1/nfs4client.py | 47 +-
> nfs4.1/nfs4commoncode.py | 10 +-
> nfs4.1/nfs4lib.py | 62 ++-
> nfs4.1/nfs4server.py | 163 +++---
> nfs4.1/nfs4state.py | 15 +-
> nfs4.1/nfs_ops.py | 89 +++
> nfs4.1/server41tests/environment.py | 4 +-
> nfs4.1/server41tests/st_block.py | 4 +-
> nfs4.1/server41tests/st_compound.py | 4 +-
> nfs4.1/server41tests/st_create_session.py | 4 +-
> nfs4.1/server41tests/st_current_stateid.py | 8 +-
> nfs4.1/server41tests/st_debug.py | 4 +-
> nfs4.1/server41tests/st_delegation.py | 4 +-
> nfs4.1/server41tests/st_destroy_clientid.py | 2 +-
> nfs4.1/server41tests/st_destroy_session.py | 4 +-
> nfs4.1/server41tests/st_exchange_id.py | 4 +-
> nfs4.1/server41tests/st_getdevicelist.py | 4 +-
> nfs4.1/server41tests/st_lookup.py | 2 +-
> nfs4.1/server41tests/st_lookupp.py | 2 +-
> nfs4.1/server41tests/st_open.py | 8 +-
> nfs4.1/server41tests/st_putfh.py | 2 +-
> nfs4.1/server41tests/st_reboot.py | 4 +-
> nfs4.1/server41tests/st_reclaim_complete.py | 2 +-
> nfs4.1/server41tests/st_rename.py | 4 +-
> nfs4.1/server41tests/st_secinfo.py | 4 +-
> nfs4.1/server41tests/st_secinfo_no_name.py | 4 +-
> nfs4.1/server41tests/st_sequence.py | 4 +-
> nfs4.1/server41tests/st_trunking.py | 4 +-
> nfs4.1/server41tests/st_verify.py | 2 +-
> nfs4.1/server_exports.py | 7 +-
> nfs4.1/setup.py | 33 +-
> nfs4.1/testclient.py | 2 +-
> nfs4.1/testserver.py | 2 +-
> nfs4.1/xdrdef/__init__.py | 0
> nfs4.1/xdrdef/mnt3.x | 68 +++
> nfs4.1/xdrdef/nfs3.x | 818 ++++++++++++++++++++++++++++
> nfs4.1/{ => xdrdef}/nfs4.x | 0
> nfs4.1/{ => xdrdef}/nfs4.x.diff | 0
> nfs4.1/{ => xdrdef}/pnfs_block.x | 0
> nfs4.1/xdrdef/portmap.x | 51 ++
> nfs4.1/{ => xdrdef}/sctrl.x | 0
> rpc/rpc.py | 26 +-
> 49 files changed, 1704 insertions(+), 389 deletions(-)
> create mode 100644 nfs4.1/nfs3client.py
> delete mode 100644 nfs4.1/nfs4_ops.py
> create mode 100644 nfs4.1/nfs_ops.py
> create mode 100644 nfs4.1/xdrdef/__init__.py
> create mode 100644 nfs4.1/xdrdef/mnt3.x
> create mode 100644 nfs4.1/xdrdef/nfs3.x
> rename nfs4.1/{ => xdrdef}/nfs4.x (100%)
> rename nfs4.1/{ => xdrdef}/nfs4.x.diff (100%)
> rename nfs4.1/{ => xdrdef}/pnfs_block.x (100%)
> create mode 100644 nfs4.1/xdrdef/portmap.x
> rename nfs4.1/{ => xdrdef}/sctrl.x (100%)
>
> --
> 1.8.5.2 (Apple Git-48)
>

2014-06-05 13:56:02

by Weston Andros Adamson

[permalink] [raw]
Subject: [PATCH pynfs v2 14/16] 4.1 server: get rid of old op_getdeviceinfo

This has been commented out for a while.

Signed-off-by: Weston Andros Adamson <[email protected]>
---
nfs4.1/nfs4server.py | 21 ---------------------
1 file changed, 21 deletions(-)

diff --git a/nfs4.1/nfs4server.py b/nfs4.1/nfs4server.py
index 3d2d4cf..7ca4d92 100755
--- a/nfs4.1/nfs4server.py
+++ b/nfs4.1/nfs4server.py
@@ -1867,27 +1867,6 @@ class NFS4Server(rpc.Server):
new_cookie >= len(list))
return encode_status(NFS4_OK, res)

-# def op_getdeviceinfo(self, arg, env): # STUB
-# check_session(env)
-# # check_cfh(env)
-# # fs = env.cfh.fs
-# # STUB - only deals with block volumes
-# kind = arg.gdia_layout_type
-# if kind != LAYOUT4_BLOCK_VOLUME:
-# return encode_status(NFS4ERR_INVAL)
-# # STUB - want to pull this from fs, not block module
-# d = block.devices.get(arg.gdia_device_id, None)
-# if d is None:
-# return encode_status(NFS4ERR_INVAL)
-# address = device_addr4(LAYOUT4_BLOCK_VOLUME, d.get_addr())
-# # Check that we don't exceed count
-# p = nfs4lib.FancyNFS4Packer()
-# p.pack_device_addr4(address)
-# if len(p.get_buffer()) > arg.gdia_maxcount:
-# return encode_status(NFS4ERR_TOOSMALL, gdir_mincount = len(p.get_buffer()))
-# res = GETDEVICEINFO4resok(address, 0)
-# return encode_status(NFS4_OK, res)
-
def op_getdeviceinfo(self, arg, env): # STUB
# STUB - ignoring notifications
check_session(env)
--
1.8.5.2 (Apple Git-48)


2014-06-05 13:55:52

by Weston Andros Adamson

[permalink] [raw]
Subject: [PATCH pynfs v2 03/16] 4.1 server: avoid traceback in DS disconnect()

Session objects have no destroy method.

Signed-off-by: Weston Andros Adamson <[email protected]>
---
nfs4.1/dataserver.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/nfs4.1/dataserver.py b/nfs4.1/dataserver.py
index aca07ee..435ddd2 100644
--- a/nfs4.1/dataserver.py
+++ b/nfs4.1/dataserver.py
@@ -59,7 +59,7 @@ class DataServer(object):
self.make_root()

def disconnect(self):
- self.sess.destroy()
+ pass

def execute(self, ops, exceptions=[], delay=5, maxretries=3):
""" execute the NFS call
--
1.8.5.2 (Apple Git-48)


2014-06-05 13:55:54

by Weston Andros Adamson

[permalink] [raw]
Subject: [PATCH pynfs v2 05/16] 4.1 client: remove unused imports

Signed-off-by: Weston Andros Adamson <[email protected]>
---
nfs4.1/nfs4client.py | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/nfs4.1/nfs4client.py b/nfs4.1/nfs4client.py
index 2aa0a2c..7a07ab7 100644
--- a/nfs4.1/nfs4client.py
+++ b/nfs4.1/nfs4client.py
@@ -8,15 +8,13 @@ from xdrdef.sctrl_pack import SCTRLPacker, SCTRLUnpacker
import nfs4_ops as op
import time, struct
import threading
-import collections
import hmac
-from locking import Lock
from nfs4commoncode import CBCompoundState as CompoundState, \
cb_encode_status as encode_status, \
cb_encode_status_by_name as encode_status_by_name


-import sys, traceback
+import traceback
import logging
logging.basicConfig(level=logging.INFO,
format="%(levelname)-7s:%(name)s:%(message)s")
--
1.8.5.2 (Apple Git-48)


2014-06-05 13:56:03

by Weston Andros Adamson

[permalink] [raw]
Subject: [PATCH pynfs v2 16/16] nfs3clnt: reconnect when sending on inactive pipe

Signed-off-by: Weston Andros Adamson <[email protected]>
---
nfs4.1/nfs3client.py | 45 +++++++++++++++++++++++++--------------------
1 file changed, 25 insertions(+), 20 deletions(-)

diff --git a/nfs4.1/nfs3client.py b/nfs4.1/nfs3client.py
index 79a6f0e..176765c 100644
--- a/nfs4.1/nfs3client.py
+++ b/nfs4.1/nfs3client.py
@@ -30,14 +30,19 @@ class PORTMAPClient(rpc.Client):
def __init__(self, host='localhost', port=PMAP_PORT):
rpc.Client.__init__(self, PMAP_PROG, PMAP_VERS)
self.server_address = (host, port)
- self.c1 = self.connect(self.server_address)
+ self._pipe = None
+
+ def get_pipe(self):
+ if not self._pipe or not self._pipe.is_active():
+ self._pipe = self.connect(self.server_address)
+ return self._pipe

def proc_async(self, procnum, procarg, credinfo=None, pipe=None,
checks=True, packer=PORTMAPPacker):
if credinfo is None:
credinfo = self.default_cred
if pipe is None:
- pipe = self.c1
+ pipe = self.get_pipe()
p = packer(check_enum=checks, check_array=checks)
arg_packer = getattr(p, 'pack_%s' % procarg.__class__.__name__)
arg_packer(procarg)
@@ -51,7 +56,7 @@ class PORTMAPClient(rpc.Client):

def listen(self, xid, restypename, pipe=None, timeout=10.0):
if pipe is None:
- pipe = self.c1
+ pipe = self.get_pipe()
header, data = pipe.listen(xid, timeout)
if data:
p = PORTMAPUnpacker(data)
@@ -69,14 +74,19 @@ class Mnt3Client(rpc.Client):
def __init__(self, host='localhost', port=None):
rpc.Client.__init__(self, MOUNT_PROGRAM, MOUNT_V3)
self.server_address = (host, port)
- self.c1 = self.connect(self.server_address)
+ self._pipe = None
+
+ def get_pipe(self):
+ if not self._pipe or not self._pipe.is_active():
+ self._pipe = self.connect(self.server_address)
+ return self._pipe

def proc_async(self, procnum, procarg, credinfo=None, pipe=None,
checks=True, packer=MNT3Packer):
if credinfo is None:
credinfo = self.default_cred
if pipe is None:
- pipe = self.c1
+ pipe = self.get_pipe()
p = packer(check_enum=checks, check_array=checks)
arg_packer = getattr(p, 'pack_%s' % procarg.__class__.__name__)
arg_packer(procarg)
@@ -90,7 +100,7 @@ class Mnt3Client(rpc.Client):

def listen(self, xid, restypename, pipe=None, timeout=10.0):
if pipe is None:
- pipe = self.c1
+ pipe = self.get_pipe()
header, data = pipe.listen(xid, timeout)
if data:
p = MNT3Unpacker(data)
@@ -110,15 +120,6 @@ class Mnt3Client(rpc.Client):
class NFS3Client(rpc.Client):
def __init__(self, host='localhost', port=None, ctrl_proc=16, summary=None):
rpc.Client.__init__(self, 100003, 3)
- #self.prog = 0x40000000
- #self.versions = [1] # List of supported versions of prog
-
- #self.minorversion = minorversion
- #self.minor_versions = [minorversion]
- #self.tag = "default tag"
- #self.impl_id = nfs_impl_id4("citi.umich.edu", "pynfs X.X",
- # nfs4lib.get_nfstime())
-
self.portmap = PORTMAPClient(host=host)
self.mntport = self.portmap.get_port(MOUNT_PROGRAM, MOUNT_V3)
if not port:
@@ -128,17 +129,21 @@ class NFS3Client(rpc.Client):

self.verifier = struct.pack('>d', time.time())
self.server_address = (host, self.port)
- self.c1 = self.connect(self.server_address)
- #self.sessions = {} # XXX Really, this should be per server
self.ctrl_proc = ctrl_proc
self.summary = summary
+ self._pipe = None
self.mntclnt = Mnt3Client(host=host, port=self.mntport)

+ def get_pipe(self):
+ if not self._pipe or not self._pipe.is_active():
+ self._pipe = self.connect(self.server_address)
+ return self._pipe
+
def set_cred(self, credinfo):
self.default_cred = credinfo

def null_async(self, data=""):
- return self.send_call(self.c1, 0, data)
+ return self.send_call(self.get_pipe(), 0, data)

def null(self, *args, **kwargs):
xid = self.null_async(*args, **kwargs)
@@ -149,7 +154,7 @@ class NFS3Client(rpc.Client):
if credinfo is None:
credinfo = self.default_cred
if pipe is None:
- pipe = self.c1
+ pipe = self.get_pipe()
p = packer(check_enum=checks, check_array=checks)
arg_packer = getattr(p, 'pack_%s' % procarg.__class__.__name__)
arg_packer(procarg)
@@ -167,7 +172,7 @@ class NFS3Client(rpc.Client):

def listen(self, xid, procarg=None, pipe=None, timeout=10.0):
if pipe is None:
- pipe = self.c1
+ pipe = self.get_pipe()
header, data = pipe.listen(xid, timeout)
if data:
p = NFS3Unpacker(data)
--
1.8.5.2 (Apple Git-48)


2014-06-05 13:56:02

by Weston Andros Adamson

[permalink] [raw]
Subject: [PATCH pynfs v2 15/16] rpc: on socket error, close and mark pipe inactive

call _event_close() on socket errors instead of tracing back and mark the
pipe as inactive so callers can reconnect as needed.

Signed-off-by: Weston Andros Adamson <[email protected]>
---
rpc/rpc.py | 26 +++++++++++++++++++++++---
1 file changed, 23 insertions(+), 3 deletions(-)

diff --git a/rpc/rpc.py b/rpc/rpc.py
index 250e945..4801883 100644
--- a/rpc/rpc.py
+++ b/rpc/rpc.py
@@ -351,6 +351,7 @@ class RpcPipe(Pipe):
self._pending = {} # {xid:defer}
self._lock = threading.Lock() # Protects fields below
self._xid = 0
+ self.set_active()

def _get_xid(self):
with self._lock:
@@ -358,6 +359,15 @@ class RpcPipe(Pipe):
self._xid = inc_u32(out)
return out

+ def set_active(self):
+ self._active = True
+
+ def clear_active(self):
+ self._active = False
+
+ def is_active(self):
+ return self._active
+
def listen(self, xid, timeout=None):
"""Wait for a reply to a CALL."""
self._pending[xid].wait(timeout)
@@ -500,15 +510,24 @@ class ConnectionHandler(object):
log_p.warn(1, "polling error from %i" % fd)
# STUB - now what?
for fd in w:
- self._event_write(fd)
+ try:
+ self._event_write(fd)
+ except socket.error, e:
+ self._event_close(fd)
for fd in r:
if fd in self.listeners:
- self._event_connect_incoming(fd)
+ try:
+ self._event_connect_incoming(fd)
+ except socket.error, e:
+ self._event_close(fd)
elif fd == self._alarm_poll.fileno():
commands = self._alarm_poll.recv(self.rsize)
for c in commands:
data = self._alarm.pop()
- switch[c](data)
+ try:
+ switch[c](data)
+ except socket.error, e:
+ self._event_close(fd)
else:
try:
data = self.sockets[fd].recv_records(self.rsize)
@@ -557,6 +576,7 @@ class ConnectionHandler(object):
self.writelist -= temp
self.readlist -= temp
self.errlist -= temp
+ self.sockets[fd].clear_active()
self.sockets[fd].close()
del self.sockets[fd]

--
1.8.5.2 (Apple Git-48)


2014-06-05 14:22:36

by Weston Andros Adamson

[permalink] [raw]
Subject: Re: [PATCH pynfs v2 00/16] prep for flex file layout server

Oh! Sorry I still needed to make it public.

Try now

-dros



On Jun 5, 2014, at 10:19 AM, J. Bruce Fields <[email protected]> wrote:

> On Thu, Jun 05, 2014 at 09:55:28AM -0400, Weston Andros Adamson wrote:
>> Changes in v2:
>>
>> - moved "4.1 client: reclaim_complete after create_session" to
>> "dataserver: reclaim_complete after create_session" as the implicit
>> reclaim complete is needed in DS path, but not in all server tests.
>>
>> - dropped "4.1 server: service RECLAIM_COMPLETE operations" as it's
>> unneeded.
>>
>> - formatted these patches with -M flag so we can see moved files
>>
>> .. and I pushed the changes to my ff_prep branch.
>>
>> Thanks!
>> -dros
>>
>>
>> These patches are in preparation for the pynfs implementation of a flex
>> file layout server.
>>
>> I already have patches for a working flex file server, but I figure those
>> should wait until the spec is complete ;)
>>
>> I pushed these patches to my linux-nfs.org tree on branch 'ff_prep':
>>
>> git://git.linux-nfs.org/projects/dros/pynfs.git
>
> $ git pull git://git.linux-nfs.org/projects/dros/pynfs.git ff_prep
>
> fatal: remote error: access denied or repository not exported:
> /projects/dros/pynfs.git
>
> No big deal, just using git-am instead.....
>
> --b.
>
>>
>> The prep includes:
>>
>> - patches that enable pynfs mds using real v4.1 DSes (on the backend,
>> not usable from clients as there is no stateid sharing between mds and ds)
>>
>> - fix several bugs in pnfs path
>>
>> - move .x files to subdir 'xdrdef' - the nfs4.1 directory was getting crowded
>> and we're going to add several more .x files along with all of the
>> autogenerated files. Note this change touches server tests too.
>>
>> - clean up the nfs4server's output - no longer print out EVERY part of EVERY
>> operation which was very efficient at hiding tracebacks and made pynfs
>> even slower. Old functionality is now switched on with -v flag. Also
>> added an in-between mode "-s" that prints a summary of whats going on.
>>
>> - support for NFSv3 backend communication - this is not actually used yet,
>> but can be tested with file layout by always returning
>> NFS4ERR_LAYOUTUNAVAILABLE in layoutget and using DataServer3 class instead
>> of DataServer41
>>
>>
>> Weston Andros Adamson (16):
>> dataserver: reclaim_complete after create_session
>> dataserver: only catch connection error
>> 4.1 server: avoid traceback in DS disconnect()
>> move .x files to subdir 'xdrdef'
>> 4.1 client: remove unused imports
>> 4.1 server: add -v flag & silence random output
>> 4.1 server: add -s option to print summary of ops
>> dataserver: make generic interface to ops
>> dataserver: don't import * from nfs4 specific mods
>> 4.1 server: move nfs4_ops.py to nfs_ops.py
>> add mntv3, portmapv2 and nfsv3 .x files
>> dataserver: separate generic and 4.1 code
>> 4.1 server: add support for NFSv3 data servers
>> 4.1 server: get rid of old op_getdeviceinfo
>> rpc: on socket error, close and mark pipe inactive
>> nfs3clnt: reconnect when sending on inactive pipe
>>
>> nfs4.1/block.py | 8 +-
>> nfs4.1/client41tests/environment.py | 4 +-
>> nfs4.1/config.py | 8 +-
>> nfs4.1/dataserver.py | 308 ++++++++---
>> nfs4.1/fs.py | 38 +-
>> nfs4.1/nfs3client.py | 185 +++++++
>> nfs4.1/nfs4_ops.py | 61 ---
>> nfs4.1/nfs4client.py | 47 +-
>> nfs4.1/nfs4commoncode.py | 10 +-
>> nfs4.1/nfs4lib.py | 62 ++-
>> nfs4.1/nfs4server.py | 163 +++---
>> nfs4.1/nfs4state.py | 15 +-
>> nfs4.1/nfs_ops.py | 89 +++
>> nfs4.1/server41tests/environment.py | 4 +-
>> nfs4.1/server41tests/st_block.py | 4 +-
>> nfs4.1/server41tests/st_compound.py | 4 +-
>> nfs4.1/server41tests/st_create_session.py | 4 +-
>> nfs4.1/server41tests/st_current_stateid.py | 8 +-
>> nfs4.1/server41tests/st_debug.py | 4 +-
>> nfs4.1/server41tests/st_delegation.py | 4 +-
>> nfs4.1/server41tests/st_destroy_clientid.py | 2 +-
>> nfs4.1/server41tests/st_destroy_session.py | 4 +-
>> nfs4.1/server41tests/st_exchange_id.py | 4 +-
>> nfs4.1/server41tests/st_getdevicelist.py | 4 +-
>> nfs4.1/server41tests/st_lookup.py | 2 +-
>> nfs4.1/server41tests/st_lookupp.py | 2 +-
>> nfs4.1/server41tests/st_open.py | 8 +-
>> nfs4.1/server41tests/st_putfh.py | 2 +-
>> nfs4.1/server41tests/st_reboot.py | 4 +-
>> nfs4.1/server41tests/st_reclaim_complete.py | 2 +-
>> nfs4.1/server41tests/st_rename.py | 4 +-
>> nfs4.1/server41tests/st_secinfo.py | 4 +-
>> nfs4.1/server41tests/st_secinfo_no_name.py | 4 +-
>> nfs4.1/server41tests/st_sequence.py | 4 +-
>> nfs4.1/server41tests/st_trunking.py | 4 +-
>> nfs4.1/server41tests/st_verify.py | 2 +-
>> nfs4.1/server_exports.py | 7 +-
>> nfs4.1/setup.py | 33 +-
>> nfs4.1/testclient.py | 2 +-
>> nfs4.1/testserver.py | 2 +-
>> nfs4.1/xdrdef/__init__.py | 0
>> nfs4.1/xdrdef/mnt3.x | 68 +++
>> nfs4.1/xdrdef/nfs3.x | 818 ++++++++++++++++++++++++++++
>> nfs4.1/{ => xdrdef}/nfs4.x | 0
>> nfs4.1/{ => xdrdef}/nfs4.x.diff | 0
>> nfs4.1/{ => xdrdef}/pnfs_block.x | 0
>> nfs4.1/xdrdef/portmap.x | 51 ++
>> nfs4.1/{ => xdrdef}/sctrl.x | 0
>> rpc/rpc.py | 26 +-
>> 49 files changed, 1704 insertions(+), 389 deletions(-)
>> create mode 100644 nfs4.1/nfs3client.py
>> delete mode 100644 nfs4.1/nfs4_ops.py
>> create mode 100644 nfs4.1/nfs_ops.py
>> create mode 100644 nfs4.1/xdrdef/__init__.py
>> create mode 100644 nfs4.1/xdrdef/mnt3.x
>> create mode 100644 nfs4.1/xdrdef/nfs3.x
>> rename nfs4.1/{ => xdrdef}/nfs4.x (100%)
>> rename nfs4.1/{ => xdrdef}/nfs4.x.diff (100%)
>> rename nfs4.1/{ => xdrdef}/pnfs_block.x (100%)
>> create mode 100644 nfs4.1/xdrdef/portmap.x
>> rename nfs4.1/{ => xdrdef}/sctrl.x (100%)
>>
>> --
>> 1.8.5.2 (Apple Git-48)
>>


2014-06-05 13:55:57

by Weston Andros Adamson

[permalink] [raw]
Subject: [PATCH pynfs v2 09/16] dataserver: don't import * from nfs4 specific mods

don't pollute the global namespace with constants and types from nfs4_*

this is in preparation for NFSv3 DSes.

Signed-off-by: Weston Andros Adamson <[email protected]>
---
nfs4.1/dataserver.py | 60 ++++++++++++++++++++++++++--------------------------
1 file changed, 30 insertions(+), 30 deletions(-)

diff --git a/nfs4.1/dataserver.py b/nfs4.1/dataserver.py
index 16be4c4..f9e9740 100644
--- a/nfs4.1/dataserver.py
+++ b/nfs4.1/dataserver.py
@@ -1,8 +1,8 @@
import rpc
import nfs4lib
-from xdrdef.nfs4_type import *
+import xdrdef.nfs4_type as type4
from xdrdef.nfs4_pack import NFS4Packer
-from xdrdef.nfs4_const import *
+import xdrdef.nfs4_const as const4
import time
import logging
import nfs4client
@@ -56,7 +56,7 @@ class DataServer41(object):
c = self.c1.new_client("DS.init_%s" % self.server)
# This is a hack to ensure MDS/DS communication path is at least
# as wide as the client/MDS channel (at least for linux client)
- fore_attrs = channel_attrs4(0, 16384, 16384, 2868, 8, 8, [])
+ fore_attrs = type4.channel_attrs4(0, 16384, 16384, 2868, 8, 8, [])
self.sess = c.create_session(fore_attrs=fore_attrs)
sess.compound([op.reclaim_complete(FALSE)])
self.make_root()
@@ -69,12 +69,12 @@ class DataServer41(object):
If an error code is specified in the exceptions it means that the
caller wants to handle the error himself
"""
- retry_errors = [NFS4ERR_DELAY, NFS4ERR_GRACE]
- state_errors = [NFS4ERR_STALE_CLIENTID, NFS4ERR_BADSESSION,
- NFS4ERR_BADSLOT, NFS4ERR_DEADSESSION]
+ retry_errors = [const4.NFS4ERR_DELAY, const4.NFS4ERR_GRACE]
+ state_errors = [const4.NFS4ERR_STALE_CLIENTID, const4.NFS4ERR_BADSESSION,
+ const4.NFS4ERR_BADSLOT, const4.NFS4ERR_DEADSESSION]
while True:
res = self.sess.compound(ops)
- if res.status == NFS4_OK or res.status in exceptions:
+ if res.status == const4.NFS4_OK or res.status in exceptions:
return res
elif res.status in retry_errors:
if maxretries > 0:
@@ -96,7 +96,7 @@ class DataServer41(object):
uaddr = '.'.join([self.server,
str(self.port >> 8),
str(self.port & 0xff)])
- return netaddr4(self.proto, uaddr)
+ return type4.netaddr4(self.proto, uaddr)

def get_multipath_netaddr4s(self):
netaddr4s = []
@@ -109,24 +109,24 @@ class DataServer41(object):
if server.find(':') >= 0:
proto = "tcp6"

- netaddr4s.append(netaddr4(proto, uaddr))
+ netaddr4s.append(type4.netaddr4(proto, uaddr))
return netaddr4s


- def make_root(self, attrs={FATTR4_MODE:0777}):
+ def make_root(self, attrs={const4.FATTR4_MODE:0777}):
existing_path = []
- kind = createtype4(NF4DIR)
+ kind = type4.createtype4(const4.NF4DIR)
for comp in self.path:
existing_path.append(comp)
res = self._execute(nfs4lib.use_obj(existing_path),
- exceptions=[NFS4ERR_NOENT])
- if res.status == NFS4ERR_NOENT:
+ exceptions=[const4.NFS4ERR_NOENT])
+ if res.status == const4.NFS4ERR_NOENT:
cr_ops = nfs4lib.use_obj(existing_path[:-1]) + \
[op.create(kind, comp, attrs)]
self._execute(cr_ops)
res = self._execute(nfs4lib.use_obj(self.path) + [op.getfh()])
self.path_fh = res.resarray[-1].object
- need = ACCESS4_READ | ACCESS4_LOOKUP | ACCESS4_MODIFY | ACCESS4_EXTEND
+ need = const4.ACCESS4_READ | const4.ACCESS4_LOOKUP | const4.ACCESS4_MODIFY | const4.ACCESS4_EXTEND
res = self._execute(nfs4lib.use_obj(self.path_fh) + [op.access(need)])
if res.resarray[-1].access != need:
raise RuntimeError
@@ -136,25 +136,25 @@ class DataServer41(object):
return hashlib.sha1("%r" % mds_fh).hexdigest()

def open_file(self, mds_fh, seqid=0,
- access=OPEN4_SHARE_ACCESS_BOTH, deny=OPEN4_SHARE_DENY_NONE,
- attrs={FATTR4_MODE: 0777}, owner = "mds", mode=GUARDED4):
+ access=const4.OPEN4_SHARE_ACCESS_BOTH, deny=const4.OPEN4_SHARE_DENY_NONE,
+ attrs={const4.FATTR4_MODE: 0777}, owner = "mds", mode=const4.GUARDED4):
verifier = self.sess.c.verifier
- openflag = openflag4(OPEN4_CREATE, createhow4(mode, attrs, verifier))
+ openflag = type4.openflag4(const4.OPEN4_CREATE, type4.createhow4(mode, attrs, verifier))
name = self.fh_to_name(mds_fh)
while True:
if mds_fh in self.filehandles:
return
open_op = op.open(seqid, access, deny,
- open_owner4(self.sess.client.clientid, owner),
- openflag, open_claim4(CLAIM_NULL, name))
- res = self._execute(nfs4lib.use_obj(self.path_fh) + [open_op, op.getfh()], exceptions=[NFS4ERR_EXIST])
- if res.status == NFS4_OK:
+ type4.open_owner4(self.sess.client.clientid, owner),
+ openflag, type4.open_claim4(const4.CLAIM_NULL, name))
+ res = self._execute(nfs4lib.use_obj(self.path_fh) + [open_op, op.getfh()], exceptions=[const4.NFS4ERR_EXIST])
+ if res.status == const4.NFS4_OK:
ds_fh = res.resarray[-1].opgetfh.resok4.object
- ds_openstateid = stateid4(0, res.resarray[-2].stateid.other)
+ ds_openstateid = type4.stateid4(0, res.resarray[-2].stateid.other)
self.filehandles[mds_fh] = (ds_fh, ds_openstateid)
return
- elif res.status == NFS4ERR_EXIST:
- openflag = openflag4(OPEN4_NOCREATE)
+ elif res.status == const4.NFS4ERR_EXIST:
+ openflag = type4.openflag4(const4.OPEN4_NOCREATE)
else:
raise RuntimeError

@@ -177,26 +177,26 @@ class DataServer41(object):

def write(self, fh, pos, data):
ops = [op.putfh(fh),
- op.write(nfs4lib.state00, pos, FILE_SYNC4, data)]
+ op.write(nfs4lib.state00, pos, const4.FILE_SYNC4, data)]
# There are all sorts of error handling issues here
res = self._execute(ops)

def truncate(self, fh, size):
ops = [op.putfh(fh),
- op.setattr(nfs4lib.state00, {FATTR4_SIZE: size})]
+ op.setattr(nfs4lib.state00, {const4.FATTR4_SIZE: size})]
res = self._execute(ops)

def get_size(self, fh):
ops = [op.putfh(fh),
- op.getattr(1L << FATTR4_SIZE)]
+ op.getattr(1L << const4.FATTR4_SIZE)]
res = self._execute(ops)
attrdict = res.resarray[-1].obj_attributes
- return attrdict.get(FATTR4_SIZE, 0)
+ return attrdict.get(const4.FATTR4_SIZE, 0)


class DSDevice(object):
def __init__(self, mdsds):
- self.list = [] # list of DataServer instances
+ self.list = [] # list of DataServer41 instances
# STUB only one data group supported for now
self.devid = 0
self.active = 0
@@ -248,7 +248,7 @@ class DSDevice(object):
netaddrs.append(multipath)
stripe_indices.append(index)
index = index + 1
- addr = nfsv4_1_file_layout_ds_addr4(stripe_indices, netaddrs)
+ addr = type4.nfsv4_1_file_layout_ds_addr4(stripe_indices, netaddrs)
p = NFS4Packer()
p.pack_nfsv4_1_file_layout_ds_addr4(addr)
return p.get_buffer()
--
1.8.5.2 (Apple Git-48)


2014-06-05 14:24:42

by J. Bruce Fields

[permalink] [raw]
Subject: Re: [PATCH pynfs v2 00/16] prep for flex file layout server

On Thu, Jun 05, 2014 at 10:22:33AM -0400, Weston Andros Adamson wrote:
> Oh! Sorry I still needed to make it public.
>
> Try now

Works for me now, thanks!--b.

2014-06-05 13:55:59

by Weston Andros Adamson

[permalink] [raw]
Subject: [PATCH pynfs v2 11/16] add mntv3, portmapv2 and nfsv3 .x files

mntv3 and nfsv3 .x files made from IETF specs by Tom Haynes
<[email protected]>.

portmap2 .x files made from IETF specs by Weston Andros Adamson
<[email protected]>.

Signed-off-by: Weston Andros Adamson <[email protected]>
---
nfs4.1/xdrdef/mnt3.x | 68 ++++
nfs4.1/xdrdef/nfs3.x | 818 ++++++++++++++++++++++++++++++++++++++++++++++++
nfs4.1/xdrdef/portmap.x | 51 +++
3 files changed, 937 insertions(+)
create mode 100644 nfs4.1/xdrdef/mnt3.x
create mode 100644 nfs4.1/xdrdef/nfs3.x
create mode 100644 nfs4.1/xdrdef/portmap.x

diff --git a/nfs4.1/xdrdef/mnt3.x b/nfs4.1/xdrdef/mnt3.x
new file mode 100644
index 0000000..b632322
--- /dev/null
+++ b/nfs4.1/xdrdef/mnt3.x
@@ -0,0 +1,68 @@
+const MNTPATHLEN = 1024; /* Maximum bytes in a path name */
+const MNTNAMLEN = 255; /* Maximum bytes in a name */
+const FHSIZE3 = 64; /* Maximum bytes in a V3 file handle */
+
+typedef opaque fhandle3 <FHSIZE3>;
+typedef string dirpath <MNTPATHLEN>;
+typedef string name <MNTNAMLEN>;
+
+struct mountres3_ok {
+ fhandle3 fhandle;
+ int auth_flavors <>;
+};
+
+union mountres3 switch (mountstat3 fhs_status) {
+case MNT3_OK:
+ mountres3_ok mountinfo;
+default:
+ void;
+};
+
+struct mountbody {
+ name ml_hostname;
+ dirpath ml_directory;
+ mountlist ml_next;
+};
+
+typedef mountbody *mountlist;
+
+
+struct groupnode {
+ name gr_name;
+ groups gr_next;
+};
+
+typedef groupnode *groups;
+
+
+struct exportnode {
+ dirpath ex_dir;
+ groups ex_groups;
+ exports ex_next;
+};
+
+typedef exportnode *exports;
+
+enum mountstat3 {
+ MNT3_OK = 0, /* no error */
+ MNT3ERR_PERM = 1, /* Not owner */
+ MNT3ERR_NOENT = 2, /* No such file or directory */
+ MNT3ERR_IO = 5, /* I/O error */
+ MNT3ERR_ACCES = 13, /* Permission denied */
+ MNT3ERR_NOTDIR = 20, /* Not a directory */
+ MNT3ERR_INVAL = 22, /* Invalid argument */
+ MNT3ERR_NAMETOOLONG = 63, /* Filename too long */
+ MNT3ERR_NOTSUPP = 10004, /* Operation not supported */
+ MNT3ERR_SERVERFAULT = 10006 /* A failure on the server */
+};
+
+program MOUNT_PROGRAM {
+ version MOUNT_V3 {
+ void MOUNTPROC3_NULL(void) = 0;
+ mountres3 MOUNTPROC3_MNT(dirpath) = 1;
+ mountlist MOUNTPROC3_DUMP(void) = 2;
+ void MOUNTPROC3_UMNT(dirpath) = 3;
+ void MOUNTPROC3_UMNTALL(void) = 4;
+ exports MOUNTPROC3_EXPORT(void) = 5;
+ } = 3;
+} = 100005;
diff --git a/nfs4.1/xdrdef/nfs3.x b/nfs4.1/xdrdef/nfs3.x
new file mode 100644
index 0000000..ddd1395
--- /dev/null
+++ b/nfs4.1/xdrdef/nfs3.x
@@ -0,0 +1,818 @@
+const NFS3_FHSIZE = 64; /* Maximum bytes in a V3 file handle */
+
+const FALSE = 0;
+const TRUE = 1;
+
+const NFS3_COOKIEVERFSIZE = 8;
+const NFS3_CREATEVERFSIZE = 8;
+const NFS3_WRITEVERFSIZE = 8;
+
+typedef unsigned hyper uint64;
+typedef hyper int64;
+typedef unsigned int uint32;
+typedef int int32;
+typedef string filename3 <>;
+typedef string nfspath3 <>;
+typedef uint64 fileid3;
+typedef uint64 cookie3;
+typedef opaque cookieverf3[NFS3_COOKIEVERFSIZE];
+typedef opaque createverf3[NFS3_CREATEVERFSIZE];
+typedef opaque writeverf3[NFS3_WRITEVERFSIZE];
+typedef uint32 uid3;
+typedef uint32 gid3;
+typedef uint64 size3;
+typedef uint64 offset3;
+typedef uint32 mode3;
+typedef uint32 count3;
+
+enum nfsstat3 {
+ NFS3_OK = 0,
+ NFS3ERR_PERM = 1,
+ NFS3ERR_NOENT = 2,
+ NFS3ERR_IO = 5,
+ NFS3ERR_NXIO = 6,
+ NFS3ERR_ACCES = 13,
+ NFS3ERR_EXIST = 17,
+ NFS3ERR_XDEV = 18,
+ NFS3ERR_NODEV = 19,
+ NFS3ERR_NOTDIR = 20,
+ NFS3ERR_ISDIR = 21,
+ NFS3ERR_INVAL = 22,
+ NFS3ERR_FBIG = 27,
+ NFS3ERR_NOSPC = 28,
+ NFS3ERR_ROFS = 30,
+ NFS3ERR_MLINK = 31,
+ NFS3ERR_NAMETOOLONG = 63,
+ NFS3ERR_NOTEMPTY = 66,
+ NFS3ERR_DQUOT = 69,
+ NFS3ERR_STALE = 70,
+ NFS3ERR_REMOTE = 71,
+ NFS3ERR_BADHANDLE = 10001,
+ NFS3ERR_NOT_SYNC = 10002,
+ NFS3ERR_BAD_COOKIE = 10003,
+ NFS3ERR_NOTSUPP = 10004,
+ NFS3ERR_TOOSMALL = 10005,
+ NFS3ERR_SERVERFAULT = 10006,
+ NFS3ERR_BADTYPE = 10007,
+ NFS3ERR_JUKEBOX = 10008
+};
+
+enum ftype3 {
+ NF3REG = 1,
+ NF3DIR = 2,
+ NF3BLK = 3,
+ NF3CHR = 4,
+ NF3LNK = 5,
+ NF3SOCK = 6,
+ NF3FIFO = 7
+};
+
+struct specdata3 {
+ uint32 specdata1;
+ uint32 specdata2;
+};
+
+struct nfs_fh3 {
+ opaque data <NFS3_FHSIZE>;
+};
+
+struct nfstime3 {
+ uint32 seconds;
+ uint32 nseconds;
+};
+
+struct fattr3 {
+ ftype3 type;
+ mode3 mode;
+ uint32 nlink;
+ uid3 uid;
+ gid3 gid;
+ size3 size;
+ size3 used;
+ specdata3 rdev;
+ uint64 fsid;
+ fileid3 fileid;
+ nfstime3 atime;
+ nfstime3 mtime;
+ nfstime3 ctime;
+};
+
+union post_op_attr switch (bool attributes_follow) {
+case TRUE:
+ fattr3 attributes;
+case FALSE:
+ void;
+};
+
+struct wcc_attr {
+ size3 size;
+ nfstime3 mtime;
+ nfstime3 ctime;
+};
+
+union pre_op_attr switch (bool attributes_follow) {
+case TRUE:
+ wcc_attr attributes;
+case FALSE:
+ void;
+};
+
+struct wcc_data {
+ pre_op_attr before;
+ post_op_attr after;
+};
+
+union post_op_fh3 switch (bool handle_follows) {
+case TRUE:
+ nfs_fh3 handle;
+case FALSE:
+ void;
+};
+
+enum time_how {
+ DONT_CHANGE = 0,
+ SET_TO_SERVER_TIME = 1,
+ SET_TO_CLIENT_TIME = 2
+};
+
+union set_mode3 switch (bool set_it) {
+case TRUE:
+ mode3 mode;
+default:
+ void;
+};
+
+union set_uid3 switch (bool set_it) {
+case TRUE:
+ uid3 uid;
+default:
+ void;
+};
+
+union set_gid3 switch (bool set_it) {
+case TRUE:
+ gid3 gid;
+default:
+ void;
+};
+
+union set_size3 switch (bool set_it) {
+case TRUE:
+ size3 size;
+default:
+ void;
+};
+
+union set_atime switch (time_how set_it) {
+case SET_TO_CLIENT_TIME:
+ nfstime3 atime;
+default:
+ void;
+};
+
+union set_mtime switch (time_how set_it) {
+case SET_TO_CLIENT_TIME:
+ nfstime3 mtime;
+default:
+ void;
+};
+
+struct sattr3 {
+ set_mode3 mode;
+ set_uid3 uid;
+ set_gid3 gid;
+ set_size3 size;
+ set_atime atime;
+ set_mtime mtime;
+};
+
+struct diropargs3 {
+ nfs_fh3 dir;
+ filename3 name;
+};
+
+struct GETATTR3args {
+ nfs_fh3 object;
+};
+
+struct GETATTR3resok {
+ fattr3 obj_attributes;
+};
+
+union GETATTR3res switch (nfsstat3 status) {
+case NFS3_OK:
+ GETATTR3resok resok;
+default:
+ void;
+};
+
+union sattrguard3 switch (bool check) {
+case TRUE:
+ nfstime3 obj_ctime;
+case FALSE:
+ void;
+};
+
+struct SETATTR3args {
+ nfs_fh3 object;
+ sattr3 new_attributes;
+ sattrguard3 guard;
+};
+
+struct SETATTR3resok {
+ wcc_data obj_wcc;
+};
+
+struct SETATTR3resfail {
+ wcc_data obj_wcc;
+};
+
+union SETATTR3res switch (nfsstat3 status) {
+case NFS3_OK:
+ SETATTR3resok resok;
+default:
+ SETATTR3resfail resfail;
+};
+
+struct LOOKUP3args {
+ diropargs3 what;
+};
+
+struct LOOKUP3resok {
+ nfs_fh3 object;
+ post_op_attr obj_attributes;
+ post_op_attr dir_attributes;
+};
+
+struct LOOKUP3resfail {
+ post_op_attr dir_attributes;
+};
+
+union LOOKUP3res switch (nfsstat3 status) {
+case NFS3_OK:
+ LOOKUP3resok resok;
+default:
+ LOOKUP3resfail resfail;
+};
+
+const ACCESS3_READ = 0x0001;
+const ACCESS3_LOOKUP = 0x0002;
+const ACCESS3_MODIFY = 0x0004;
+const ACCESS3_EXTEND = 0x0008;
+const ACCESS3_DELETE = 0x0010;
+const ACCESS3_EXECUTE = 0x0020;
+
+struct ACCESS3args {
+ nfs_fh3 object;
+ uint32 access;
+};
+
+struct ACCESS3resok {
+ post_op_attr obj_attributes;
+ uint32 access;
+};
+
+struct ACCESS3resfail {
+ post_op_attr obj_attributes;
+};
+
+union ACCESS3res switch (nfsstat3 status) {
+case NFS3_OK:
+ ACCESS3resok resok;
+default:
+ ACCESS3resfail resfail;
+};
+
+struct READLINK3args {
+ nfs_fh3 symlink;
+};
+
+struct READLINK3resok {
+ post_op_attr symlink_attributes;
+ nfspath3 data;
+};
+
+struct READLINK3resfail {
+ post_op_attr symlink_attributes;
+};
+
+union READLINK3res switch (nfsstat3 status) {
+case NFS3_OK:
+ READLINK3resok resok;
+default:
+ READLINK3resfail resfail;
+};
+
+struct READ3args {
+ nfs_fh3 file;
+ offset3 offset;
+ count3 count;
+};
+
+struct READ3resok {
+ post_op_attr file_attributes;
+ count3 count;
+ bool eof;
+ opaque data <>;
+};
+
+struct READ3resfail {
+ post_op_attr file_attributes;
+};
+
+union READ3res switch (nfsstat3 status) {
+case NFS3_OK:
+ READ3resok resok;
+default:
+ READ3resfail resfail;
+};
+
+enum stable_how {
+ UNSTABLE = 0,
+ DATA_SYNC = 1,
+ FILE_SYNC = 2
+};
+
+struct WRITE3args {
+ nfs_fh3 file;
+ offset3 offset;
+ count3 count;
+ stable_how stable;
+ opaque data <>;
+};
+
+struct WRITE3resok {
+ wcc_data file_wcc;
+ count3 count;
+ stable_how committed;
+ writeverf3 verf;
+};
+
+struct WRITE3resfail {
+ wcc_data file_wcc;
+};
+
+union WRITE3res switch (nfsstat3 status) {
+case NFS3_OK:
+ WRITE3resok resok;
+default:
+ WRITE3resfail resfail;
+};
+
+enum createmode3 {
+ UNCHECKED = 0,
+ GUARDED = 1,
+ EXCLUSIVE = 2
+};
+
+union createhow3 switch (createmode3 mode) {
+case UNCHECKED:
+case GUARDED:
+ sattr3 obj_attributes;
+case EXCLUSIVE:
+ createverf3 verf;
+};
+
+struct CREATE3args {
+ diropargs3 where;
+ createhow3 how;
+};
+
+struct CREATE3resok {
+ post_op_fh3 obj;
+ post_op_attr obj_attributes;
+ wcc_data dir_wcc;
+};
+
+struct CREATE3resfail {
+ wcc_data dir_wcc;
+};
+
+union CREATE3res switch (nfsstat3 status) {
+case NFS3_OK:
+ CREATE3resok resok;
+default:
+ CREATE3resfail resfail;
+};
+
+struct MKDIR3args {
+ diropargs3 where;
+ sattr3 attributes;
+};
+
+struct MKDIR3resok {
+ post_op_fh3 obj;
+ post_op_attr obj_attributes;
+ wcc_data dir_wcc;
+};
+
+struct MKDIR3resfail {
+ wcc_data dir_wcc;
+};
+
+union MKDIR3res switch (nfsstat3 status) {
+case NFS3_OK:
+ MKDIR3resok resok;
+default:
+ MKDIR3resfail resfail;
+};
+
+struct symlinkdata3 {
+ sattr3 symlink_attributes;
+ nfspath3 symlink_data;
+};
+
+struct SYMLINK3args {
+ diropargs3 where;
+ symlinkdata3 symlink;
+};
+
+struct SYMLINK3resok {
+ post_op_fh3 obj;
+ post_op_attr obj_attributes;
+ wcc_data dir_wcc;
+};
+
+struct SYMLINK3resfail {
+ wcc_data dir_wcc;
+};
+
+union SYMLINK3res switch (nfsstat3 status) {
+case NFS3_OK:
+ SYMLINK3resok resok;
+default:
+ SYMLINK3resfail resfail;
+};
+
+struct devicedata3 {
+ sattr3 dev_attributes;
+ specdata3 spec;
+};
+
+union mknoddata3 switch (ftype3 type) {
+case NF3CHR:
+case NF3BLK:
+ devicedata3 device;
+case NF3SOCK:
+case NF3FIFO:
+ sattr3 pipe_attributes;
+default:
+ void;
+};
+
+struct MKNOD3args {
+ diropargs3 where;
+ mknoddata3 what;
+};
+
+struct MKNOD3resok {
+ post_op_fh3 obj;
+ post_op_attr obj_attributes;
+ wcc_data dir_wcc;
+};
+
+struct MKNOD3resfail {
+ wcc_data dir_wcc;
+};
+
+union MKNOD3res switch (nfsstat3 status) {
+case NFS3_OK:
+ MKNOD3resok resok;
+default:
+ MKNOD3resfail resfail;
+};
+
+struct REMOVE3args {
+ diropargs3 object;
+};
+
+struct REMOVE3resok {
+ wcc_data dir_wcc;
+};
+
+struct REMOVE3resfail {
+ wcc_data dir_wcc;
+};
+
+union REMOVE3res switch (nfsstat3 status) {
+case NFS3_OK:
+ REMOVE3resok resok;
+default:
+ REMOVE3resfail resfail;
+};
+
+struct RMDIR3args {
+ diropargs3 object;
+};
+
+struct RMDIR3resok {
+ wcc_data dir_wcc;
+};
+
+struct RMDIR3resfail {
+ wcc_data dir_wcc;
+};
+
+union RMDIR3res switch (nfsstat3 status) {
+case NFS3_OK:
+ RMDIR3resok resok;
+default:
+ RMDIR3resfail resfail;
+};
+
+struct RENAME3args {
+ diropargs3 fromfile;
+ diropargs3 tofile;
+};
+
+struct RENAME3resok {
+ wcc_data fromdir_wcc;
+ wcc_data todir_wcc;
+};
+
+struct RENAME3resfail {
+ wcc_data fromdir_wcc;
+ wcc_data todir_wcc;
+};
+
+union RENAME3res switch (nfsstat3 status) {
+case NFS3_OK:
+ RENAME3resok resok;
+default:
+ RENAME3resfail resfail;
+};
+
+struct LINK3args {
+ nfs_fh3 file;
+ diropargs3 link;
+};
+
+struct LINK3resok {
+ post_op_attr file_attributes;
+ wcc_data linkdir_wcc;
+};
+
+struct LINK3resfail {
+ post_op_attr file_attributes;
+ wcc_data linkdir_wcc;
+};
+
+union LINK3res switch (nfsstat3 status) {
+case NFS3_OK:
+ LINK3resok resok;
+default:
+ LINK3resfail resfail;
+};
+
+struct READDIR3args {
+ nfs_fh3 dir;
+ cookie3 cookie;
+ cookieverf3 cookieverf;
+ count3 count;
+};
+
+struct entry3 {
+ fileid3 fileid;
+ filename3 name;
+ cookie3 cookie;
+ entry3 *nextentry;
+};
+
+struct dirlist3 {
+ entry3 *entries;
+ bool eof;
+};
+
+struct READDIR3resok {
+ post_op_attr dir_attributes;
+ cookieverf3 cookieverf;
+ dirlist3 reply;
+};
+
+struct READDIR3resfail {
+ post_op_attr dir_attributes;
+};
+
+union READDIR3res switch (nfsstat3 status) {
+case NFS3_OK:
+ READDIR3resok resok;
+default:
+ READDIR3resfail resfail;
+};
+
+struct READDIRPLUS3args {
+ nfs_fh3 dir;
+ cookie3 cookie;
+ cookieverf3 cookieverf;
+ count3 dircount;
+ count3 maxcount;
+};
+
+struct entryplus3 {
+ fileid3 fileid;
+ filename3 name;
+ cookie3 cookie;
+ post_op_attr name_attributes;
+ post_op_fh3 name_handle;
+ entryplus3 *nextentry;
+};
+
+struct dirlistplus3 {
+ entryplus3 *entries;
+ bool eof;
+};
+
+struct READDIRPLUS3resok {
+ post_op_attr dir_attributes;
+ cookieverf3 cookieverf;
+ dirlistplus3 reply;
+};
+
+struct READDIRPLUS3resfail {
+ post_op_attr dir_attributes;
+};
+
+union READDIRPLUS3res switch (nfsstat3 status) {
+case NFS3_OK:
+ READDIRPLUS3resok resok;
+default:
+ READDIRPLUS3resfail resfail;
+};
+
+struct FSSTAT3args {
+ nfs_fh3 fsroot;
+};
+
+struct FSSTAT3resok {
+ post_op_attr obj_attributes;
+ size3 tbytes;
+ size3 fbytes;
+ size3 abytes;
+ size3 tfiles;
+ size3 ffiles;
+ size3 afiles;
+ uint32 invarsec;
+};
+
+struct FSSTAT3resfail {
+ post_op_attr obj_attributes;
+};
+
+union FSSTAT3res switch (nfsstat3 status) {
+case NFS3_OK:
+ FSSTAT3resok resok;
+default:
+ FSSTAT3resfail resfail;
+};
+
+const FSF3_LINK = 0x0001;
+const FSF3_SYMLINK = 0x0002;
+const FSF3_HOMOGENEOUS = 0x0008;
+const FSF3_CANSETTIME = 0x0010;
+
+struct FSINFOargs {
+ nfs_fh3 fsroot;
+};
+
+struct FSINFO3resok {
+ post_op_attr obj_attributes;
+ uint32 rtmax;
+ uint32 rtpref;
+ uint32 rtmult;
+ uint32 wtmax;
+ uint32 wtpref;
+ uint32 wtmult;
+ uint32 dtpref;
+ size3 maxfilesize;
+ nfstime3 time_delta;
+ uint32 properties;
+};
+
+struct FSINFO3resfail {
+ post_op_attr obj_attributes;
+};
+
+union FSINFO3res switch (nfsstat3 status) {
+case NFS3_OK:
+ FSINFO3resok resok;
+default:
+ FSINFO3resfail resfail;
+};
+
+struct PATHCONF3args {
+ nfs_fh3 object;
+};
+
+struct PATHCONF3resok {
+ post_op_attr obj_attributes;
+ uint32 linkmax;
+ uint32 name_max;
+ bool no_trunc;
+ bool chown_restricted;
+ bool case_insensitive;
+ bool case_preserving;
+};
+
+struct PATHCONF3resfail {
+ post_op_attr obj_attributes;
+};
+
+union PATHCONF3res switch (nfsstat3 status) {
+case NFS3_OK:
+ PATHCONF3resok resok;
+default:
+ PATHCONF3resfail resfail;
+};
+
+struct COMMIT3args {
+ nfs_fh3 file;
+ offset3 offset;
+ count3 count;
+};
+
+struct COMMIT3resok {
+ wcc_data file_wcc;
+ writeverf3 verf;
+};
+
+struct COMMIT3resfail {
+ wcc_data file_wcc;
+};
+
+union COMMIT3res switch (nfsstat3 status) {
+case NFS3_OK:
+ COMMIT3resok resok;
+default:
+ COMMIT3resfail resfail;
+};
+
+program NFS_PROGRAM {
+ version NFS_V3 {
+
+ void
+ NFSPROC3_NULL(void) = 0;
+
+ GETATTR3res
+ NFSPROC3_GETATTR(GETATTR3args) = 1;
+
+ SETATTR3res
+ NFSPROC3_SETATTR(SETATTR3args) = 2;
+
+ LOOKUP3res
+ NFSPROC3_LOOKUP(LOOKUP3args) = 3;
+
+ ACCESS3res
+ NFSPROC3_ACCESS(ACCESS3args) = 4;
+
+ READLINK3res
+ NFSPROC3_READLINK(READLINK3args) = 5;
+
+ READ3res
+ NFSPROC3_READ(READ3args) = 6;
+
+ WRITE3res
+ NFSPROC3_WRITE(WRITE3args) = 7;
+
+ CREATE3res
+ NFSPROC3_CREATE(CREATE3args) = 8;
+
+ MKDIR3res
+ NFSPROC3_MKDIR(MKDIR3args) = 9;
+
+ SYMLINK3res
+ NFSPROC3_SYMLINK(SYMLINK3args) = 10;
+
+ MKNOD3res
+ NFSPROC3_MKNOD(MKNOD3args) = 11;
+
+ REMOVE3res
+ NFSPROC3_REMOVE(REMOVE3args) = 12;
+
+ RMDIR3res
+ NFSPROC3_RMDIR(RMDIR3args) = 13;
+
+ RENAME3res
+ NFSPROC3_RENAME(RENAME3args) = 14;
+
+ LINK3res
+ NFSPROC3_LINK(LINK3args) = 15;
+
+ READDIR3res
+ NFSPROC3_READDIR(READDIR3args) = 16;
+
+ READDIRPLUS3res
+ NFSPROC3_READDIRPLUS(READDIRPLUS3args) = 17;
+
+ FSSTAT3res
+ NFSPROC3_FSSTAT(FSSTAT3args) = 18;
+
+ FSINFO3res
+ NFSPROC3_FSINFO(FSINFO3args) = 19;
+
+ PATHCONF3res
+ NFSPROC3_PATHCONF(PATHCONF3args) = 20;
+
+ COMMIT3res
+ NFSPROC3_COMMIT(COMMIT3args) = 21;
+ } = 3;
+} = 100003;
diff --git a/nfs4.1/xdrdef/portmap.x b/nfs4.1/xdrdef/portmap.x
new file mode 100644
index 0000000..1158d4e
--- /dev/null
+++ b/nfs4.1/xdrdef/portmap.x
@@ -0,0 +1,51 @@
+const PMAP_PORT = 111; /* portmapper port number */
+
+struct mapping {
+ unsigned int prog;
+ unsigned int vers;
+ unsigned int prot;
+ unsigned int port;
+};
+
+const IPPROTO_TCP = 6; /* protocol number for TCP/IP */
+const IPPROTO_UDP = 17; /* protocol number for UDP/IP */
+
+struct pmaplist {
+ mapping map;
+ pmaplist next;
+};
+
+struct call_args {
+ unsigned int prog;
+ unsigned int vers;
+ unsigned int proc;
+ opaque args<>;
+};
+
+struct call_result {
+ unsigned int port;
+ opaque res<>;
+};
+
+program PMAP_PROG {
+ version PMAP_VERS {
+ void
+ PMAPPROC_NULL(void) = 0;
+
+ bool
+ PMAPPROC_SET(mapping) = 1;
+
+ bool
+ PMAPPROC_UNSET(mapping) = 2;
+
+ unsigned int
+ PMAPPROC_GETPORT(mapping) = 3;
+
+ pmaplist
+ PMAPPROC_DUMP(void) = 4;
+
+ call_result
+ PMAPPROC_CALLIT(call_args) = 5;
+ } = 2;
+} = 100000;
+
--
1.8.5.2 (Apple Git-48)


2014-06-10 01:41:12

by Weston Andros Adamson

[permalink] [raw]
Subject: Re: [PATCH pynfs v2 00/16] prep for flex file layout server

On Jun 9, 2014, at 5:25 PM, J. Bruce Fields <[email protected]> wrote:

> On Thu, Jun 05, 2014 at 09:55:28AM -0400, Weston Andros Adamson wrote:
>> Changes in v2:
>>
>> - moved "4.1 client: reclaim_complete after create_session" to
>> "dataserver: reclaim_complete after create_session" as the implicit
>> reclaim complete is needed in DS path, but not in all server tests.
>>
>> - dropped "4.1 server: service RECLAIM_COMPLETE operations" as it's
>> unneeded.
>>
>> - formatted these patches with -M flag so we can see moved files
>>
>> .. and I pushed the changes to my ff_prep branch.
>
> Thanks for the patches! Applied, checked that they didn't break
> anything for me, and pushed out.
>
> (The only thing I noticed was that I had to rebuild things, to account
> for the renamed files.)
>

Great, thanks!

-dros


> --b.
>
>>
>> Thanks!
>> -dros
>>
>>
>> These patches are in preparation for the pynfs implementation of a flex
>> file layout server.
>>
>> I already have patches for a working flex file server, but I figure those
>> should wait until the spec is complete ;)
>>
>> I pushed these patches to my linux-nfs.org tree on branch 'ff_prep':
>>
>> git://git.linux-nfs.org/projects/dros/pynfs.git
>>
>> The prep includes:
>>
>> - patches that enable pynfs mds using real v4.1 DSes (on the backend,
>> not usable from clients as there is no stateid sharing between mds and ds)
>>
>> - fix several bugs in pnfs path
>>
>> - move .x files to subdir 'xdrdef' - the nfs4.1 directory was getting crowded
>> and we're going to add several more .x files along with all of the
>> autogenerated files. Note this change touches server tests too.
>>
>> - clean up the nfs4server's output - no longer print out EVERY part of EVERY
>> operation which was very efficient at hiding tracebacks and made pynfs
>> even slower. Old functionality is now switched on with -v flag. Also
>> added an in-between mode "-s" that prints a summary of whats going on.
>>
>> - support for NFSv3 backend communication - this is not actually used yet,
>> but can be tested with file layout by always returning
>> NFS4ERR_LAYOUTUNAVAILABLE in layoutget and using DataServer3 class instead
>> of DataServer41
>>
>>
>> Weston Andros Adamson (16):
>> dataserver: reclaim_complete after create_session
>> dataserver: only catch connection error
>> 4.1 server: avoid traceback in DS disconnect()
>> move .x files to subdir 'xdrdef'
>> 4.1 client: remove unused imports
>> 4.1 server: add -v flag & silence random output
>> 4.1 server: add -s option to print summary of ops
>> dataserver: make generic interface to ops
>> dataserver: don't import * from nfs4 specific mods
>> 4.1 server: move nfs4_ops.py to nfs_ops.py
>> add mntv3, portmapv2 and nfsv3 .x files
>> dataserver: separate generic and 4.1 code
>> 4.1 server: add support for NFSv3 data servers
>> 4.1 server: get rid of old op_getdeviceinfo
>> rpc: on socket error, close and mark pipe inactive
>> nfs3clnt: reconnect when sending on inactive pipe
>>
>> nfs4.1/block.py | 8 +-
>> nfs4.1/client41tests/environment.py | 4 +-
>> nfs4.1/config.py | 8 +-
>> nfs4.1/dataserver.py | 308 ++++++++---
>> nfs4.1/fs.py | 38 +-
>> nfs4.1/nfs3client.py | 185 +++++++
>> nfs4.1/nfs4_ops.py | 61 ---
>> nfs4.1/nfs4client.py | 47 +-
>> nfs4.1/nfs4commoncode.py | 10 +-
>> nfs4.1/nfs4lib.py | 62 ++-
>> nfs4.1/nfs4server.py | 163 +++---
>> nfs4.1/nfs4state.py | 15 +-
>> nfs4.1/nfs_ops.py | 89 +++
>> nfs4.1/server41tests/environment.py | 4 +-
>> nfs4.1/server41tests/st_block.py | 4 +-
>> nfs4.1/server41tests/st_compound.py | 4 +-
>> nfs4.1/server41tests/st_create_session.py | 4 +-
>> nfs4.1/server41tests/st_current_stateid.py | 8 +-
>> nfs4.1/server41tests/st_debug.py | 4 +-
>> nfs4.1/server41tests/st_delegation.py | 4 +-
>> nfs4.1/server41tests/st_destroy_clientid.py | 2 +-
>> nfs4.1/server41tests/st_destroy_session.py | 4 +-
>> nfs4.1/server41tests/st_exchange_id.py | 4 +-
>> nfs4.1/server41tests/st_getdevicelist.py | 4 +-
>> nfs4.1/server41tests/st_lookup.py | 2 +-
>> nfs4.1/server41tests/st_lookupp.py | 2 +-
>> nfs4.1/server41tests/st_open.py | 8 +-
>> nfs4.1/server41tests/st_putfh.py | 2 +-
>> nfs4.1/server41tests/st_reboot.py | 4 +-
>> nfs4.1/server41tests/st_reclaim_complete.py | 2 +-
>> nfs4.1/server41tests/st_rename.py | 4 +-
>> nfs4.1/server41tests/st_secinfo.py | 4 +-
>> nfs4.1/server41tests/st_secinfo_no_name.py | 4 +-
>> nfs4.1/server41tests/st_sequence.py | 4 +-
>> nfs4.1/server41tests/st_trunking.py | 4 +-
>> nfs4.1/server41tests/st_verify.py | 2 +-
>> nfs4.1/server_exports.py | 7 +-
>> nfs4.1/setup.py | 33 +-
>> nfs4.1/testclient.py | 2 +-
>> nfs4.1/testserver.py | 2 +-
>> nfs4.1/xdrdef/__init__.py | 0
>> nfs4.1/xdrdef/mnt3.x | 68 +++
>> nfs4.1/xdrdef/nfs3.x | 818 ++++++++++++++++++++++++++++
>> nfs4.1/{ => xdrdef}/nfs4.x | 0
>> nfs4.1/{ => xdrdef}/nfs4.x.diff | 0
>> nfs4.1/{ => xdrdef}/pnfs_block.x | 0
>> nfs4.1/xdrdef/portmap.x | 51 ++
>> nfs4.1/{ => xdrdef}/sctrl.x | 0
>> rpc/rpc.py | 26 +-
>> 49 files changed, 1704 insertions(+), 389 deletions(-)
>> create mode 100644 nfs4.1/nfs3client.py
>> delete mode 100644 nfs4.1/nfs4_ops.py
>> create mode 100644 nfs4.1/nfs_ops.py
>> create mode 100644 nfs4.1/xdrdef/__init__.py
>> create mode 100644 nfs4.1/xdrdef/mnt3.x
>> create mode 100644 nfs4.1/xdrdef/nfs3.x
>> rename nfs4.1/{ => xdrdef}/nfs4.x (100%)
>> rename nfs4.1/{ => xdrdef}/nfs4.x.diff (100%)
>> rename nfs4.1/{ => xdrdef}/pnfs_block.x (100%)
>> create mode 100644 nfs4.1/xdrdef/portmap.x
>> rename nfs4.1/{ => xdrdef}/sctrl.x (100%)
>>
>> --
>> 1.8.5.2 (Apple Git-48)
>>


2014-06-05 13:55:57

by Weston Andros Adamson

[permalink] [raw]
Subject: [PATCH pynfs v2 08/16] dataserver: make generic interface to ops

Hide the execute method to make DataServer objects more generic.

Signed-off-by: Weston Andros Adamson <[email protected]>
---
nfs4.1/dataserver.py | 41 ++++++++++++++++++++++++++++++++++-------
nfs4.1/fs.py | 24 ++++--------------------
2 files changed, 38 insertions(+), 27 deletions(-)

diff --git a/nfs4.1/dataserver.py b/nfs4.1/dataserver.py
index dd81b20..16be4c4 100644
--- a/nfs4.1/dataserver.py
+++ b/nfs4.1/dataserver.py
@@ -64,7 +64,7 @@ class DataServer41(object):
def disconnect(self):
pass

- def execute(self, ops, exceptions=[], delay=5, maxretries=3):
+ def _execute(self, ops, exceptions=[], delay=5, maxretries=3):
""" execute the NFS call
If an error code is specified in the exceptions it means that the
caller wants to handle the error himself
@@ -118,16 +118,16 @@ class DataServer41(object):
kind = createtype4(NF4DIR)
for comp in self.path:
existing_path.append(comp)
- res = self.execute(nfs4lib.use_obj(existing_path),
+ res = self._execute(nfs4lib.use_obj(existing_path),
exceptions=[NFS4ERR_NOENT])
if res.status == NFS4ERR_NOENT:
cr_ops = nfs4lib.use_obj(existing_path[:-1]) + \
[op.create(kind, comp, attrs)]
- self.execute(cr_ops)
- res = self.execute(nfs4lib.use_obj(self.path) + [op.getfh()])
+ self._execute(cr_ops)
+ res = self._execute(nfs4lib.use_obj(self.path) + [op.getfh()])
self.path_fh = res.resarray[-1].object
need = ACCESS4_READ | ACCESS4_LOOKUP | ACCESS4_MODIFY | ACCESS4_EXTEND
- res = self.execute(nfs4lib.use_obj(self.path_fh) + [op.access(need)])
+ res = self._execute(nfs4lib.use_obj(self.path_fh) + [op.access(need)])
if res.resarray[-1].access != need:
raise RuntimeError
# XXX clean DS directory
@@ -147,7 +147,7 @@ class DataServer41(object):
open_op = op.open(seqid, access, deny,
open_owner4(self.sess.client.clientid, owner),
openflag, open_claim4(CLAIM_NULL, name))
- res = self.execute(nfs4lib.use_obj(self.path_fh) + [open_op, op.getfh()], exceptions=[NFS4ERR_EXIST])
+ res = self._execute(nfs4lib.use_obj(self.path_fh) + [open_op, op.getfh()], exceptions=[NFS4ERR_EXIST])
if res.status == NFS4_OK:
ds_fh = res.resarray[-1].opgetfh.resok4.object
ds_openstateid = stateid4(0, res.resarray[-2].stateid.other)
@@ -163,10 +163,37 @@ class DataServer41(object):
seqid=0 #FIXME: seqid must be !=0
fh, stateid = self.filehandles[mds_fh]
ops = [op.putfh(fh)] + [op.close(seqid, stateid)]
- res = self.execute(ops)
+ res = self._execute(ops)
# ignoring return
del self.filehandles[mds_fh]

+ def read(self, fh, pos, count):
+ ops = [op.putfh(fh),
+ op.read(nfs4lib.state00, pos, count)]
+ # There are all sorts of error handling issues here
+ res = self._execute(ops)
+ data = res.resarray[-1].data
+ return data
+
+ def write(self, fh, pos, data):
+ ops = [op.putfh(fh),
+ op.write(nfs4lib.state00, pos, FILE_SYNC4, data)]
+ # There are all sorts of error handling issues here
+ res = self._execute(ops)
+
+ def truncate(self, fh, size):
+ ops = [op.putfh(fh),
+ op.setattr(nfs4lib.state00, {FATTR4_SIZE: size})]
+ res = self._execute(ops)
+
+ def get_size(self, fh):
+ ops = [op.putfh(fh),
+ op.getattr(1L << FATTR4_SIZE)]
+ res = self._execute(ops)
+ attrdict = res.resarray[-1].obj_attributes
+ return attrdict.get(FATTR4_SIZE, 0)
+
+
class DSDevice(object):
def __init__(self, mdsds):
self.list = [] # list of DataServer instances
diff --git a/nfs4.1/fs.py b/nfs4.1/fs.py
index 6ef283b..8fc49ef 100644
--- a/nfs4.1/fs.py
+++ b/nfs4.1/fs.py
@@ -1567,12 +1567,7 @@ class FilelayoutVolWrapper(object):
self._pos = 0

def read(self, count):
- # STUB stateid0 is illegal to a ds
- ops = [op.putfh(self._fh),
- op.read(nfs4lib.state00, self._pos, count)]
- # There are all sorts of error handling issues here
- res = self._ds.execute(ops)
- data = res.resarray[-1].data
+ data = self._ds.read(self._fh, self._pos, count)
self._pos += len(data)
return data

@@ -1580,25 +1575,14 @@ class FilelayoutVolWrapper(object):
self._pos = offset

def write(self, data):
- ops = [op.putfh(self._fh),
- op.write(nfs4lib.state00, self._pos, FILE_SYNC4, data)]
- # There are all sorts of error handling issues here
- res = self._ds.execute(ops)
+ self._ds.write(self._fh, self._pos, data)
self._pos += len(data)
- return

def truncate(self, size):
- ops = [op.putfh(self._fh),
- op.setattr(nfs4lib.state00, {FATTR4_SIZE: size})]
- res = self._ds.execute(ops)
- return
+ self._ds.truncate(self._fh, size)

def get_size(self):
- ops = [op.putfh(self._fh),
- op.getattr(1L << FATTR4_SIZE)]
- res = self._ds.execute(ops)
- attrdict = res.resarray[-1].obj_attributes
- return attrdict.get(FATTR4_SIZE, 0)
+ return self._ds.get_size(self._fh)

################################################

--
1.8.5.2 (Apple Git-48)


2014-06-05 13:55:58

by Weston Andros Adamson

[permalink] [raw]
Subject: [PATCH pynfs v2 10/16] 4.1 server: move nfs4_ops.py to nfs_ops.py

Also replace ugly exec & inspect code to just define a class with
a __getattr__ switch.

Signed-off-by: Weston Andros Adamson <[email protected]>
---
nfs4.1/dataserver.py | 32 ++++++++++---------
nfs4.1/fs.py | 2 --
nfs4.1/nfs4_ops.py | 61 -----------------------------------
nfs4.1/nfs4client.py | 14 +++++----
nfs4.1/nfs4lib.py | 8 +++--
nfs4.1/nfs4state.py | 8 +++--
nfs4.1/nfs_ops.py | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 124 insertions(+), 90 deletions(-)
delete mode 100644 nfs4.1/nfs4_ops.py
create mode 100644 nfs4.1/nfs_ops.py

diff --git a/nfs4.1/dataserver.py b/nfs4.1/dataserver.py
index f9e9740..d092cf7 100644
--- a/nfs4.1/dataserver.py
+++ b/nfs4.1/dataserver.py
@@ -8,11 +8,13 @@ import logging
import nfs4client
import hashlib
import sys
-import nfs4_ops as op
+import nfs_ops
import socket

log = logging.getLogger("Dataserver Manager")

+op4 = nfs_ops.NFS4ops()
+
class DataServer41(object):
def __init__(self, server, port, path, flavor=rpc.AUTH_SYS, active=True, mdsds=True, multipath_servers=None, summary=None):
self.mdsds = mdsds
@@ -122,12 +124,12 @@ class DataServer41(object):
exceptions=[const4.NFS4ERR_NOENT])
if res.status == const4.NFS4ERR_NOENT:
cr_ops = nfs4lib.use_obj(existing_path[:-1]) + \
- [op.create(kind, comp, attrs)]
+ [op4.create(kind, comp, attrs)]
self._execute(cr_ops)
- res = self._execute(nfs4lib.use_obj(self.path) + [op.getfh()])
+ res = self._execute(nfs4lib.use_obj(self.path) + [op4.getfh()])
self.path_fh = res.resarray[-1].object
need = const4.ACCESS4_READ | const4.ACCESS4_LOOKUP | const4.ACCESS4_MODIFY | const4.ACCESS4_EXTEND
- res = self._execute(nfs4lib.use_obj(self.path_fh) + [op.access(need)])
+ res = self._execute(nfs4lib.use_obj(self.path_fh) + [op4.access(need)])
if res.resarray[-1].access != need:
raise RuntimeError
# XXX clean DS directory
@@ -144,10 +146,10 @@ class DataServer41(object):
while True:
if mds_fh in self.filehandles:
return
- open_op = op.open(seqid, access, deny,
+ open_op = op4.open(seqid, access, deny,
type4.open_owner4(self.sess.client.clientid, owner),
openflag, type4.open_claim4(const4.CLAIM_NULL, name))
- res = self._execute(nfs4lib.use_obj(self.path_fh) + [open_op, op.getfh()], exceptions=[const4.NFS4ERR_EXIST])
+ res = self._execute(nfs4lib.use_obj(self.path_fh) + [open_op, op4.getfh()], exceptions=[const4.NFS4ERR_EXIST])
if res.status == const4.NFS4_OK:
ds_fh = res.resarray[-1].opgetfh.resok4.object
ds_openstateid = type4.stateid4(0, res.resarray[-2].stateid.other)
@@ -162,33 +164,33 @@ class DataServer41(object):
"""close the given file"""
seqid=0 #FIXME: seqid must be !=0
fh, stateid = self.filehandles[mds_fh]
- ops = [op.putfh(fh)] + [op.close(seqid, stateid)]
+ ops = [op4.putfh(fh)] + [op4.close(seqid, stateid)]
res = self._execute(ops)
# ignoring return
del self.filehandles[mds_fh]

def read(self, fh, pos, count):
- ops = [op.putfh(fh),
- op.read(nfs4lib.state00, pos, count)]
+ ops = [op4.putfh(fh),
+ op4.read(nfs4lib.state00, pos, count)]
# There are all sorts of error handling issues here
res = self._execute(ops)
data = res.resarray[-1].data
return data

def write(self, fh, pos, data):
- ops = [op.putfh(fh),
- op.write(nfs4lib.state00, pos, const4.FILE_SYNC4, data)]
+ ops = [op4.putfh(fh),
+ op4.write(nfs4lib.state00, pos, const4.FILE_SYNC4, data)]
# There are all sorts of error handling issues here
res = self._execute(ops)

def truncate(self, fh, size):
- ops = [op.putfh(fh),
- op.setattr(nfs4lib.state00, {const4.FATTR4_SIZE: size})]
+ ops = [op4.putfh(fh),
+ op4.setattr(nfs4lib.state00, {const4.FATTR4_SIZE: size})]
res = self._execute(ops)

def get_size(self, fh):
- ops = [op.putfh(fh),
- op.getattr(1L << const4.FATTR4_SIZE)]
+ ops = [op4.putfh(fh),
+ op4.getattr(1L << const4.FATTR4_SIZE)]
res = self._execute(ops)
attrdict = res.resarray[-1].obj_attributes
return attrdict.get(const4.FATTR4_SIZE, 0)
diff --git a/nfs4.1/fs.py b/nfs4.1/fs.py
index 8fc49ef..8947014 100644
--- a/nfs4.1/fs.py
+++ b/nfs4.1/fs.py
@@ -1557,8 +1557,6 @@ class FileLayoutFile(object): # XXX This should inherit from fs_base.py
vol = FilelayoutVolWrapper(self._obj, device.list[index])
return vol, v_pos, remaining

-import nfs4_ops as op
-
class FilelayoutVolWrapper(object):
def __init__(self, obj, dataserver):
self._obj = obj
diff --git a/nfs4.1/nfs4_ops.py b/nfs4.1/nfs4_ops.py
deleted file mode 100644
index 35a10ca..0000000
--- a/nfs4.1/nfs4_ops.py
+++ /dev/null
@@ -1,61 +0,0 @@
-"""For each OP_<NAME> in nfs_argop4 and nfs_cb_argop4, create a function
-<name>() that returns the appropriate *_argop4 structure, hiding
-this routine packing from the user.
-"""
-import xdrdef.nfs4_type as _type
-import xdrdef.nfs4_const as _const
-
-# This string is our general function template
-code = """\
-def %(funct_name)s(%(funct_args)s):
- %(create_args)s
- return _type.%(argop)s(_const.OP_%(enum_name)s, %(set_args)s)
-"""
-
-def _mappings():
- return _pull_argops(_const.nfs_opnum4) + _pull_argops(_const.nfs_cb_opnum4)
-
-def _pull_argops(op_dict):
- """ For each entry in op_dict, create an appropriate dictionary that can
- be used to fill the 'code' template.
- """
- import inspect
- out = []
- keys = op_dict.keys()
- keys.sort() # Not necessary, but makes scanning the printout easier
- for k in keys:
- # Create a dictionary that will be used to fill the 'code' template
- d = {}
- d["enum_name"] = enum_name = op_dict[k][3:] # <NAME>
- d["funct_name"] = "%s" % enum_name.lower() # <name>
- class_name = "%s4args" % enum_name
- klass = getattr(_type, class_name, None)
- if klass is None:
- # This operation takes no arguments
- d["funct_args"] = d["create_args"] = d["set_args"] = ""
- else:
- if type(klass) is dict:
- arg_list = "enum_value"
- d["create_args"] = "args = enum_value"
- else:
- arg_list = ", ".join(inspect.getargspec(klass.__init__)[0][1:])
- d["create_args"] = "args = _type.%s(%s)" % (class_name, arg_list)
- d["funct_args"] = arg_list
- if enum_name.startswith("CB_"):
- d["set_args"] = "opcb%s=args" % enum_name.lower()[3:]
- else:
- d["set_args"] = "op%s=args" % enum_name.lower()
- if enum_name.startswith("CB_"):
- d["argop"] = "nfs_cb_argop4"
- else:
- d["argop"] = "nfs_argop4"
- out.append(d)
- return out
-
-if __name__ == "__main__":
- for _d in _mappings():
- print code % _d
-else:
- for _d in _mappings():
- exec code % _d
-
diff --git a/nfs4.1/nfs4client.py b/nfs4.1/nfs4client.py
index 4ae884a..6912565 100644
--- a/nfs4.1/nfs4client.py
+++ b/nfs4.1/nfs4client.py
@@ -5,7 +5,7 @@ from nfs4lib import NFS4Error, NFS4Replay, inc_u32
from xdrdef.nfs4_type import *
from xdrdef.nfs4_const import *
from xdrdef.sctrl_pack import SCTRLPacker, SCTRLUnpacker
-import nfs4_ops as op
+import nfs_ops
import time, struct
import threading
import hmac
@@ -20,6 +20,8 @@ logging.basicConfig(level=logging.INFO,
format="%(levelname)-7s:%(name)s:%(message)s")
log_cb = logging.getLogger("nfs.client.cb")

+op4 = nfs_ops.NFS4ops()
+
class NFS4Client(rpc.Client, rpc.Server):
def __init__(self, host='localhost', port=2049, minorversion=1, ctrl_proc=16, summary=None):
rpc.Client.__init__(self, 100003, 4)
@@ -275,7 +277,7 @@ class NFS4Client(rpc.Client, rpc.Server):
owner = client_owner4(verf, name)
if protect is None:
protect = state_protect4_a(SP4_NONE)
- res = self.compound([op.exchange_id(owner, flags, protect,
+ res = self.compound([op4.exchange_id(owner, flags, protect,
[self.impl_id])],
cred)
nfs4lib.check(res, expect)
@@ -287,7 +289,7 @@ class NFS4Client(rpc.Client, rpc.Server):
def new_client_session(self, name, flags=0, sec=None):
c = self.new_client(name, flags=flags)
s = c.create_session(sec=sec)
- s.compound([op.reclaim_complete(FALSE)])
+ s.compound([op4.reclaim_complete(FALSE)])
return s

class ClientStateProtection(object):
@@ -339,7 +341,7 @@ class ClientRecord(object):
if prog is None:
prog = self.c.prog
for item in xrange(max_retries):
- res = self.c.compound([op.create_session(self.clientid, self.seqid,
+ res = self.c.compound([op4.create_session(self.clientid, self.seqid,
flags,
fore_attrs, back_attrs,
prog, sec)],
@@ -429,7 +431,7 @@ class SessionRecord(object):
raise RuntimeError
slot = self.fore_channel.slots[slot]
# STUB, need to properly set highest
- return op.sequence(self.sessionid, slot.get_seqid(seq_delta),
+ return op4.sequence(self.sessionid, slot.get_seqid(seq_delta),
slot.id, slot.id, cache_this)

def set_ssv(self, ssv=None, *args, **kwargs):
@@ -442,7 +444,7 @@ class SessionRecord(object):
p = nfs4lib.FancyNFS4Packer()
p.pack_SEQUENCE4args(seq_op.opsequence)
digest = protect.context.hmac(p.get_buffer(), SSV4_SUBKEY_MIC_I2T)
- ssv_op = op.set_ssv(ssv, digest)
+ ssv_op = op4.set_ssv(ssv, digest)
res = self.c.compound([seq_op, ssv_op], *args, **kwargs)
# STUB - do some checking
protect.context.set_ssv(ssv)
diff --git a/nfs4.1/nfs4lib.py b/nfs4.1/nfs4lib.py
index 116324a..02352e1 100644
--- a/nfs4.1/nfs4lib.py
+++ b/nfs4.1/nfs4lib.py
@@ -3,7 +3,7 @@ import rpc
import xdrdef.nfs4_const
from xdrdef.nfs4_pack import NFS4Packer, NFS4Unpacker
import xdrdef.nfs4_type
-import nfs4_ops as op
+import nfs_ops
import time
import collections
import hmac
@@ -30,6 +30,8 @@ state01 = xdrdef.nfs4_type.stateid4(1, "\0" * 12)

import hashlib # Note this requires 2.5 or higher

+op4 = nfs_ops.NFS4ops()
+
# Note that all the oid strings have tag and length bytes prepended, as
# per description of sec_oid4 in draft26 sect 3.2

@@ -626,9 +628,9 @@ def use_obj(file):
if file is None or file == [None]:
return []
elif type(file) is str:
- return [op.putfh(file)]
+ return [op4.putfh(file)]
else:
- return [op.putrootfh()] + [op.lookup(comp) for comp in file]
+ return [op4.putrootfh()] + [op4.lookup(comp) for comp in file]

###############################################
# Attribute information
diff --git a/nfs4.1/nfs4state.py b/nfs4.1/nfs4state.py
index 2f3cd59..2214c0d 100644
--- a/nfs4.1/nfs4state.py
+++ b/nfs4.1/nfs4state.py
@@ -8,12 +8,14 @@ from nfs4lib import NFS4Error
#from xdrdef.nfs4_type import stateid4
from xdrdef.nfs4_type import *
from xdrdef.nfs4_const import *
-import nfs4_ops as op
+import nfs_ops
import rpc
import logging

log = logging.getLogger("nfs.server.state")

+op4 = nfs_ops.NFS4ops()
+
POSIXLOCK = False

SHARE, BYTE, DELEG, LAYOUT, ANON = range(5) # State types
@@ -748,9 +750,9 @@ class DelegEntry(StateTableEntry):
# ANSWER - we care about self.status, which can be set to
# INVALID anytime by deleg_return
slot = session.channel_back.choose_slot()
- seq_op = op.cb_sequence(session.sessionid, slot.get_seqid(),
+ seq_op = op4.cb_sequence(session.sessionid, slot.get_seqid(),
slot.id, slot.id, True, []) # STUB
- recall_op = op.cb_recall(self.get_id(cb=True), False, self.file.fh)
+ recall_op = op4.cb_recall(self.get_id(cb=True), False, self.file.fh)
if self.invalid:
# Race here doesn't matter, but would like to avoid the
# RPC if possible.
diff --git a/nfs4.1/nfs_ops.py b/nfs4.1/nfs_ops.py
new file mode 100644
index 0000000..0753716
--- /dev/null
+++ b/nfs4.1/nfs_ops.py
@@ -0,0 +1,89 @@
+"""For each OP_<NAME> in nfs_argop4 and nfs_cb_argop4, create a function
+<name>() that returns the appropriate *_argop4 structure, hiding
+this routine packing from the user.
+"""
+
+from xdrdef import nfs4_type
+from xdrdef import nfs4_const
+
+from xdrdef import nfs3_type
+from xdrdef import nfs3_const
+
+def nfs4_op_names():
+ skip = len('OP_')
+ ops = [ x.lower()[skip:] for x in nfs4_const.nfs_opnum4.values() ]
+ ops.extend([ x.lower()[skip:] for x in nfs4_const.nfs_cb_opnum4.values()])
+ return ops
+
+def nfs3_proc_names():
+ pre = 'NFSPROC3_'
+ skip = len(pre)
+ procs = [ x.lower()[skip:] for x in dir(nfs3_const) if x.startswith(pre) ]
+ return procs
+
+class NFSops:
+ def __init__(self, is_v4):
+ self._is_v4 = is_v4
+ if is_v4:
+ self._op_names = nfs4_op_names()
+ self._type = nfs4_type
+ self._const = nfs4_const
+ self._args_suffix = '4args'
+ self._op_prefix = 'OP_'
+ else:
+ self._op_names = nfs3_proc_names()
+ self._type = nfs3_type
+ self._const = nfs3_const
+ self._args_suffix = '3args'
+ self._op_prefix = 'NFSPROC3_'
+
+ def __getattr__(self, attrname):
+ if attrname in self._op_names:
+ return lambda *args: self._handle_op(attrname, args)
+
+ def _handle_op(self, opname, args):
+ enum_name = opname.upper()
+
+ # RPC "args" class to create
+ class_name = "%s%s" % (enum_name, self._args_suffix)
+ klass = getattr(self._type, class_name, None)
+
+ if self._is_v4:
+ # stuff class into argop
+
+ # args to pass to argop __init__
+ opnum = getattr(self._const, self._op_prefix + enum_name)
+ kwargs = {}
+
+ if klass:
+ # otherwise it takes no arguments
+ if type(klass) is dict:
+ assert len(args) == 1
+ arg = args[0]
+ else:
+ arg = klass(*args)
+
+ if enum_name.startswith("CB_"):
+ kwargs['opcb%s' % enum_name.lower()] = arg
+ else:
+ kwargs['op%s' % enum_name.lower()] = arg
+
+ if enum_name.startswith("CB_"):
+ argop = self._type.nfs_cb_argop4
+ else:
+ argop = self._type.nfs_argop4
+
+ return argop(opnum, **kwargs)
+
+ else:
+ # for v3 just return an instance
+ return klass(*args)
+
+class NFS3ops(NFSops):
+ def __init__(self):
+ NFSops.__init__(self, False)
+
+class NFS4ops(NFSops):
+ def __init__(self):
+ NFSops.__init__(self, True)
+
--
1.8.5.2 (Apple Git-48)


2014-06-05 13:56:00

by Weston Andros Adamson

[permalink] [raw]
Subject: [PATCH pynfs v2 12/16] dataserver: separate generic and 4.1 code

Signed-off-by: Weston Andros Adamson <[email protected]>
---
nfs4.1/dataserver.py | 102 ++++++++++++++++++++++++++++-----------------------
1 file changed, 57 insertions(+), 45 deletions(-)

diff --git a/nfs4.1/dataserver.py b/nfs4.1/dataserver.py
index d092cf7..5c604dc 100644
--- a/nfs4.1/dataserver.py
+++ b/nfs4.1/dataserver.py
@@ -15,7 +15,7 @@ log = logging.getLogger("Dataserver Manager")

op4 = nfs_ops.NFS4ops()

-class DataServer41(object):
+class DataServer(object):
def __init__(self, server, port, path, flavor=rpc.AUTH_SYS, active=True, mdsds=True, multipath_servers=None, summary=None):
self.mdsds = mdsds
self.server = server
@@ -43,29 +43,47 @@ class DataServer41(object):
self.active = True
if not self.mdsds:
self.connect()
+ self.make_root()

def down(self):
+ self.disconnect()
self.active = False

+ def reset(self):
+ self.down()
+ self.up()
+
+ def get_netaddr4(self):
+ # STUB server multipathing not supported yet
+ uaddr = '.'.join([self.server,
+ str(self.port >> 8),
+ str(self.port & 0xff)])
+ return type4.netaddr4(self.proto, uaddr)
+
+ def get_multipath_netaddr4s(self):
+ netaddr4s = []
+ for addr in self.multipath_servers:
+ server, port = addr
+ uaddr = '.'.join([server,
+ str(port >> 8),
+ str(port & 0xff)])
+ proto = "tcp"
+ if server.find(':') >= 0:
+ proto = "tcp6"
+
+ netaddr4s.append(type4.netaddr4(proto, uaddr))
+ return netaddr4s
+
+ def fh_to_name(self, mds_fh):
+ return hashlib.sha1("%r" % mds_fh).hexdigest()
+
def connect(self):
- # only support root with AUTH_SYS for now
- s1 = rpc.security.instance(rpc.AUTH_SYS)
- self.cred1 = s1.init_cred(uid=0, gid=0)
- self.c1 = nfs4client.NFS4Client(self.server, self.port,
- summary=self.summary)
- self.c1.set_cred(self.cred1)
- self.c1.null()
- c = self.c1.new_client("DS.init_%s" % self.server)
- # This is a hack to ensure MDS/DS communication path is at least
- # as wide as the client/MDS channel (at least for linux client)
- fore_attrs = type4.channel_attrs4(0, 16384, 16384, 2868, 8, 8, [])
- self.sess = c.create_session(fore_attrs=fore_attrs)
- sess.compound([op.reclaim_complete(FALSE)])
- self.make_root()
+ raise NotImplemented

def disconnect(self):
pass

+class DataServer41(DataServer):
def _execute(self, ops, exceptions=[], delay=5, maxretries=3):
""" execute the NFS call
If an error code is specified in the exceptions it means that the
@@ -86,36 +104,29 @@ class DataServer41(object):
log.error("Too many retries with DS %s" % self.server)
raise Exception("Dataserver communication retry error")
elif res.status in state_errors:
- self.disconnect()
- self.connect()
+ self.reset()
else:
log.error("Unhandled status %s from DS %s" %
(nfsstat4[res.status], self.server))
raise Exception("Dataserver communication error")

- def get_netaddr4(self):
- # STUB server multipathing not supported yet
- uaddr = '.'.join([self.server,
- str(self.port >> 8),
- str(self.port & 0xff)])
- return type4.netaddr4(self.proto, uaddr)
-
- def get_multipath_netaddr4s(self):
- netaddr4s = []
- for addr in self.multipath_servers:
- server, port = addr
- uaddr = '.'.join([server,
- str(port >> 8),
- str(port & 0xff)])
- proto = "tcp"
- if server.find(':') >= 0:
- proto = "tcp6"
-
- netaddr4s.append(type4.netaddr4(proto, uaddr))
- return netaddr4s
-
+ def connect(self):
+ # only support root with AUTH_SYS for now
+ s1 = rpc.security.instance(rpc.AUTH_SYS)
+ self.cred1 = s1.init_cred(uid=0, gid=0)
+ self.c1 = nfs4client.NFS4Client(self.server, self.port,
+ summary=self.summary)
+ self.c1.set_cred(self.cred1)
+ self.c1.null()
+ c = self.c1.new_client("DS.init_%s" % self.server)
+ # This is a hack to ensure MDS/DS communication path is at least
+ # as wide as the client/MDS channel (at least for linux client)
+ fore_attrs = type4.channel_attrs4(0, 16384, 16384, 2868, 8, 8, [])
+ self.sess = c.create_session(fore_attrs=fore_attrs)
+ self.sess.compound([op4.reclaim_complete(const4.FALSE)])

- def make_root(self, attrs={const4.FATTR4_MODE:0777}):
+ def make_root(self):
+ attrs = {const4.FATTR4_MODE:0777}
existing_path = []
kind = type4.createtype4(const4.NF4DIR)
for comp in self.path:
@@ -134,12 +145,13 @@ class DataServer41(object):
raise RuntimeError
# XXX clean DS directory

- def fh_to_name(self, mds_fh):
- return hashlib.sha1("%r" % mds_fh).hexdigest()
-
- def open_file(self, mds_fh, seqid=0,
- access=const4.OPEN4_SHARE_ACCESS_BOTH, deny=const4.OPEN4_SHARE_DENY_NONE,
- attrs={const4.FATTR4_MODE: 0777}, owner = "mds", mode=const4.GUARDED4):
+ def open_file(self, mds_fh):
+ seqid=0
+ access = const4.OPEN4_SHARE_ACCESS_BOTH
+ deny = const4.OPEN4_SHARE_DENY_NONE
+ attrs = {const4.FATTR4_MODE: 0777}
+ owner = "mds"
+ mode = const4.GUARDED4
verifier = self.sess.c.verifier
openflag = type4.openflag4(const4.OPEN4_CREATE, type4.createhow4(mode, attrs, verifier))
name = self.fh_to_name(mds_fh)
--
1.8.5.2 (Apple Git-48)