All of lore.kernel.org
 help / color / mirror / Atom feed
From: Weston Andros Adamson <dros@primarydata.com>
To: bfields@fieldses.org
Cc: linux-nfs@vger.kernel.org, Weston Andros Adamson <dros@primarydata.com>
Subject: [PATCH pynfs 08/17] 4.1 server: add -s option to print summary of ops
Date: Wed,  4 Jun 2014 17:01:56 -0400	[thread overview]
Message-ID: <1401915726-29092-9-git-send-email-dros@primarydata.com> (raw)
In-Reply-To: <1401915726-29092-1-git-send-email-dros@primarydata.com>

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 <dros@primarydata.com>
---
 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 d697631..9b0462d 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)
@@ -172,7 +175,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]]
         """
@@ -194,8 +197,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 e504362..f5d2006 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 67adbf1..088e8c4 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):
@@ -2062,6 +2104,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,
@@ -2095,7 +2139,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)


  parent reply	other threads:[~2014-06-04 21:02 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-06-04 21:01 [PATCH pynfs 00/17] prep for flex file layout server Weston Andros Adamson
2014-06-04 21:01 ` [PATCH pynfs 01/17] 4.1 client: reclaim_complete after create_session Weston Andros Adamson
2014-06-05  2:26   ` J. Bruce Fields
2014-06-05 12:54     ` Weston Andros Adamson
2014-06-04 21:01 ` [PATCH pynfs 02/17] 4.1 server: service RECLAIM_COMPLETE operations Weston Andros Adamson
2014-06-05  2:29   ` J. Bruce Fields
2014-06-05 12:22     ` Trond Myklebust
2014-06-05 12:58       ` Weston Andros Adamson
2014-06-05 13:06         ` J. Bruce Fields
2014-06-05 13:18           ` Weston Andros Adamson
2014-06-05 13:34             ` Weston Andros Adamson
2014-06-05 13:41               ` J. Bruce Fields
2014-06-05 13:49                 ` Weston Andros Adamson
2014-06-04 21:01 ` [PATCH pynfs 03/17] dataserver: only catch connection error Weston Andros Adamson
2014-06-04 21:01 ` [PATCH pynfs 04/17] 4.1 server: avoid traceback in DS disconnect() Weston Andros Adamson
2014-06-04 21:01 ` [PATCH pynfs 06/17] 4.1 client: remove unused imports Weston Andros Adamson
2014-06-04 21:01 ` [PATCH pynfs 07/17] 4.1 server: add -v flag & silence random output Weston Andros Adamson
2014-06-04 21:01 ` Weston Andros Adamson [this message]
2014-06-04 21:01 ` [PATCH pynfs 09/17] dataserver: make generic interface to ops Weston Andros Adamson
2014-06-04 21:01 ` [PATCH pynfs 10/17] dataserver: don't import * from nfs4 specific mods Weston Andros Adamson
2014-06-04 21:01 ` [PATCH pynfs 11/17] 4.1 server: move nfs4_ops.py to nfs_ops.py Weston Andros Adamson
2014-06-04 21:02 ` [PATCH pynfs 12/17] add mntv3, portmapv2 and nfsv3 .x files Weston Andros Adamson
2014-06-05  2:34   ` J. Bruce Fields
2014-06-04 21:02 ` [PATCH pynfs 13/17] dataserver: separate generic and 4.1 code Weston Andros Adamson
2014-06-04 21:02 ` [PATCH pynfs 14/17] 4.1 server: add support for NFSv3 data servers Weston Andros Adamson
2014-06-04 21:02 ` [PATCH pynfs 15/17] 4.1 server: get rid of old op_getdeviceinfo Weston Andros Adamson
2014-06-04 21:02 ` [PATCH pynfs 15/17] nfs41 svr: " Weston Andros Adamson
2014-06-04 21:02 ` [PATCH pynfs 16/17] rpc: on socket error, close and mark pipe inactive Weston Andros Adamson
2014-06-04 21:02 ` [PATCH pynfs 17/17] nfs3clnt: reconnect when sending on inactive pipe Weston Andros Adamson
     [not found] ` <1401915726-29092-6-git-send-email-dros@primarydata.com>
2014-06-05  2:31   ` [PATCH pynfs 05/17] move .x files to subdir 'xdrdef' J. Bruce Fields
2014-06-05 12:51     ` Weston Andros Adamson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1401915726-29092-9-git-send-email-dros@primarydata.com \
    --to=dros@primarydata.com \
    --cc=bfields@fieldses.org \
    --cc=linux-nfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.