2021-10-28 18:36:05

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v5 0/9] Add a tool for using the new sysfs files

From: Anna Schumaker <[email protected]>

These patches implement a tool that can be used to read and write the
sysfs files, with subcommands!

The following subcommands are implemented:
rpcctl client
rpcctl switch
rpcctl switch set
rpcctl xprt
rpcctl xprt set

So you can print out information about every switch with:
anna@client ~ % rpcctl switch
switch 0: xprts 1, active 1, queue 0
xprt 0: local, /var/run/gssproxy.sock [main]
switch 1: xprts 1, active 1, queue 0
xprt 1: local, /var/run/rpcbind.sock [main]
switch 2: xprts 1, active 1, queue 0
xprt 2: tcp, 192.168.111.1 [main]
switch 3: xprts 4, active 4, queue 0
xprt 3: tcp, 192.168.111.188 [main]
xprt 4: tcp, 192.168.111.188
xprt 5: tcp, 192.168.111.188
xprt 6: tcp, 192.168.111.188

And information about each xprt:
anna@client ~ % rpcctl xprt
xprt 0: local, /var/run/gssproxy.sock, port 0, state <CONNECTED,BOUND>, main
Source: (einval), port 0, Requests: 2
Congestion: cur 0, win 256, Slots: min 2, max 65536
Queues: binding 0, sending 0, pending 0, backlog 0, tasks 0
xprt 1: local, /var/run/rpcbind.sock, port 0, state <CONNECTED,BOUND>, main
Source: (einval), port 0, Requests: 2
Congestion: cur 0, win 256, Slots: min 2, max 65536
Queues: binding 0, sending 0, pending 0, backlog 0, tasks 0
xprt 2: tcp, 192.168.111.1, port 2049, state <CONNECTED,BOUND>, main
Source: 192.168.111.222, port 959, Requests: 2
Congestion: cur 0, win 256, Slots: min 2, max 65536
Queues: binding 0, sending 0, pending 0, backlog 0, tasks 0
xprt 3: tcp, 192.168.111.188, port 2049, state <CONNECTED,BOUND>, main
Source: 192.168.111.222, port 921, Requests: 2
Congestion: cur 0, win 256, Slots: min 2, max 65536
Queues: binding 0, sending 0, pending 0, backlog 0, tasks 0
xprt 4: tcp, 192.168.111.188, port 2049, state <CONNECTED,BOUND>
Source: 192.168.111.222, port 726, Requests: 2
Congestion: cur 0, win 256, Slots: min 2, max 65536
Queues: binding 0, sending 0, pending 0, backlog 0, tasks 0
xprt 5: tcp, 192.168.111.188, port 2049, state <CONNECTED,BOUND>
Source: 192.168.111.222, port 671, Requests: 2
Congestion: cur 0, win 256, Slots: min 2, max 65536
Queues: binding 0, sending 0, pending 0, backlog 0, tasks 0
xprt 6: tcp, 192.168.111.188, port 2049, state <CONNECTED,BOUND>
Source: 192.168.111.222, port 934, Requests: 2
Congestion: cur 0, win 256, Slots: min 2, max 65536
Queues: binding 0, sending 0, pending 0, backlog 0, tasks 0

You can use the `set` subcommand to change the dstaddr of individual xprts:
anna@client ~ % sudo rpcctl xprt --id 4
xprt 4: tcp, 192.168.111.188, port 2049, state <CONNECTED,BOUND>
Source: 192.168.111.222, port 726, Requests: 2
Congestion: cur 0, win 256, Slots: min 2, max 65536
Queues: binding 0, sending 0, pending 0, backlog 0, tasks 0
anna@client ~ % sudo rpcctl xprt set --id 4 --dstaddr server2.nowheycreamery.com
xprt 4: tcp, 192.168.111.186, port 2049, state <CONNECTED,BOUND>
Source: 192.168.111.222, port 726, Requests: 2
Congestion: cur 0, win 256, Slots: min 2, max 65536
Queues: binding 0, sending 0, pending 0, backlog 0, tasks 0

Or for changing the dstaddr of all xprts attached to a switch:
anna@client % rpcctl switch --id 3
switch 3: xprts 4, active 4, queue 0
xprt 3: tcp, 192.168.111.188 [main]
xprt 4: tcp, 192.168.111.188
xprt 5: tcp, 192.168.111.188
xprt 6: tcp, 192.168.111.188
anna@client % sudo rpcctl switch set --id 4 --dstaddr server2.nowheycreamery.vm
switch 3: xprts 4, active 4, queue 0
xprt 2: tcp, 192.168.111.186 [main]
xprt 3: tcp, 192.168.111.186
xprt 5: tcp, 192.168.111.186
xprt 6: tcp, 192.168.111.186

Changes in v5:
- Rename from 'rpcctl' to 'rpcctl'
- Rename subcommands 'xprt-switch" to 'switch' and 'rpc-client' to 'client'
- Clean up how the displayed strings are generated
- Handle kernels that don't yet have the srcaddr patch

Thoughts?
Anna


Anna Schumaker (9):
rpcctl: Add a rpcctl.py tool
rpcctl: Add a command for printing xprt switch information
rpcctl: Add a command for printing individual xprts
rpcctl: Add a command for printing rpc client information
rpcctl: Add a command for changing xprt dstaddr
rpcctl: Add a command for changing xprt switch dstaddrs
rpcctl: Add a command for changing xprt state
rpcctl: Add a man page
rpcctl: Add installation to the Makefile

.gitignore | 2 +
configure.ac | 1 +
tools/Makefile.am | 2 +-
tools/rpcctl/Makefile.am | 20 ++++++++
tools/rpcctl/client.py | 27 +++++++++++
tools/rpcctl/rpcctl | 5 ++
tools/rpcctl/rpcctl.man | 88 ++++++++++++++++++++++++++++++++++
tools/rpcctl/rpcctl.py | 23 +++++++++
tools/rpcctl/switch.py | 51 ++++++++++++++++++++
tools/rpcctl/sysfs.py | 42 ++++++++++++++++
tools/rpcctl/xprt.py | 101 +++++++++++++++++++++++++++++++++++++++
11 files changed, 361 insertions(+), 1 deletion(-)
create mode 100644 tools/rpcctl/Makefile.am
create mode 100644 tools/rpcctl/client.py
create mode 100644 tools/rpcctl/rpcctl
create mode 100644 tools/rpcctl/rpcctl.man
create mode 100755 tools/rpcctl/rpcctl.py
create mode 100644 tools/rpcctl/switch.py
create mode 100644 tools/rpcctl/sysfs.py
create mode 100644 tools/rpcctl/xprt.py

--
2.33.1


2021-10-28 18:36:05

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v5 6/9] rpcctl: Add a command for changing xprt switch dstaddrs

From: Anna Schumaker <[email protected]>

This is basically the same as for xprts, but it iterates through all
xprts attached to the switch to apply the new address.

Signed-off-by: Anna Schumaker <[email protected]>
---
tools/rpcctl/switch.py | 15 +++++++++++++++
1 file changed, 15 insertions(+)

diff --git a/tools/rpcctl/switch.py b/tools/rpcctl/switch.py
index 497ee8b1923c..b1b287bb6578 100644
--- a/tools/rpcctl/switch.py
+++ b/tools/rpcctl/switch.py
@@ -30,7 +30,22 @@ def list_xprt_switches(args):
if args.id == None or xs.id == args.id[0]:
print(xs)

+def set_xprt_switch_property(args):
+ switch = XprtSwitch(sysfs.SUNRPC / "xprt-switches" / f"switch-{args.id[0]}")
+ try:
+ for xprt in switch.xprts:
+ xprt.set_dstaddr(args.dstaddr[0])
+ print(switch)
+ except Exception as e:
+ print(e)
+
def add_command(subparser):
parser = subparser.add_parser("switch", help="Commands for xprt switches")
parser.add_argument("--id", metavar="ID", nargs=1, type=int, help="Id of a specific xprt-switch to show")
parser.set_defaults(func=list_xprt_switches)
+
+ subparser = parser.add_subparsers()
+ parser = subparser.add_parser("set", help="Set an xprt switch property")
+ parser.add_argument("--id", metavar="ID", nargs=1, type=int, required=True, help="Id of an xprt-switch to modify")
+ parser.add_argument("--dstaddr", metavar="dstaddr", nargs=1, type=str, help="New dstaddr to set")
+ parser.set_defaults(func=set_xprt_switch_property)
--
2.33.1

2021-10-28 18:36:05

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v5 4/9] rpcctl: Add a command for printing rpc client information

From: Anna Schumaker <[email protected]>

It's mostly the same information as with xprt-switches, except with
rpc-client id prepended to the first line.

Signed-off-by: Anna Schumaker <[email protected]>
---
v5: Clean up how the RpcClient __str__() function works
Rename the subcommand to simply "client"
---
tools/rpcctl/client.py | 27 +++++++++++++++++++++++++++
tools/rpcctl/rpcctl.py | 2 ++
tools/rpcctl/switch.py | 5 +++--
3 files changed, 32 insertions(+), 2 deletions(-)
create mode 100644 tools/rpcctl/client.py

diff --git a/tools/rpcctl/client.py b/tools/rpcctl/client.py
new file mode 100644
index 000000000000..42c9bee0d2d8
--- /dev/null
+++ b/tools/rpcctl/client.py
@@ -0,0 +1,27 @@
+import sysfs
+import switch
+
+class RpcClient:
+ def __init__(self, path):
+ self.path = path
+ self.id = int(path.stem.split("-")[1])
+ self.switch = switch.XprtSwitch(path / (path / "switch").readlink(), sep=",")
+
+ def __lt__(self, rhs):
+ return self.id < rhs.id
+
+ def __str__(self):
+ return f"client {self.id}: {self.switch}"
+
+
+def list_rpc_clients(args):
+ clients = [ RpcClient(f) for f in (sysfs.SUNRPC / "rpc-clients").iterdir() ]
+ clients.sort()
+ for client in clients:
+ if args.id == None or client.id == args.id[0]:
+ print(client)
+
+def add_command(subparser):
+ parser = subparser.add_parser("client", help="Commands for rpc clients")
+ parser.add_argument("--id", metavar="ID", nargs=1, type=int, help="Id of a specific client to show")
+ parser.set_defaults(func=list_rpc_clients)
diff --git a/tools/rpcctl/rpcctl.py b/tools/rpcctl/rpcctl.py
index dfad6ac08fa0..e2172cdfa4c1 100755
--- a/tools/rpcctl/rpcctl.py
+++ b/tools/rpcctl/rpcctl.py
@@ -10,9 +10,11 @@ def show_small_help(args):
parser.set_defaults(func=show_small_help)


+import client
import switch
import xprt
subparser = parser.add_subparsers(title="commands")
+client.add_command(subparser)
switch.add_command(subparser)
xprt.add_command(subparser)

diff --git a/tools/rpcctl/switch.py b/tools/rpcctl/switch.py
index c96e70b7710f..497ee8b1923c 100644
--- a/tools/rpcctl/switch.py
+++ b/tools/rpcctl/switch.py
@@ -2,10 +2,11 @@ import sysfs
import xprt

class XprtSwitch:
- def __init__(self, path):
+ def __init__(self, path, sep=":"):
self.path = path
self.id = int(path.stem.split("-")[1])
self.info = sysfs.read_info_file(path / "xprt_switch_info")
+ self.sep = sep

self.xprts = [ xprt.Xprt(p) for p in self.path.iterdir() if p.is_dir() ]
self.xprts.sort()
@@ -14,7 +15,7 @@ class XprtSwitch:
return self.path < rhs.path

def __str__(self):
- switch = f"switch {self.id}: " \
+ switch = f"switch {self.id}{self.sep} " \
f"xprts {self.info['num_xprts']}, " \
f"active {self.info['num_active']}, " \
f"queue {self.info['queue_len']}"
--
2.33.1

2021-10-28 18:36:05

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v5 7/9] rpcctl: Add a command for changing xprt state

From: Anna Schumaker <[email protected]>

We can set it offline or online, or we can remove an xprt. The kernel
only supports removing offlined transports, so we make sure to set the
state to "offline" before sending the remove command.

Signed-off-by: Anna Schumaker <[email protected]>
---
tools/rpcctl/xprt.py | 26 +++++++++++++++++++++++---
1 file changed, 23 insertions(+), 3 deletions(-)

diff --git a/tools/rpcctl/xprt.py b/tools/rpcctl/xprt.py
index 1201140ce5af..92db756c8374 100644
--- a/tools/rpcctl/xprt.py
+++ b/tools/rpcctl/xprt.py
@@ -9,9 +9,7 @@ class Xprt:
self.info = sysfs.read_info_file(path / "xprt_info")
self.dstaddr = sysfs.read_addr_file(path / "dstaddr")
self.srcaddr = sysfs.read_addr_file(path / "srcaddr")
-
- with open(path / "xprt_state") as f:
- self.state = ','.join(f.readline().split()[1:])
+ self.read_state()

def __lt__(self, rhs):
return self.id < rhs.id
@@ -35,9 +33,16 @@ class Xprt:
f"backlog {self.info['backlog_q_len']}, tasks {self.info['tasks_queuelen']}"

def __str__(self):
+ if not self.path.exists():
+ return f"xprt {self.id}: has been removed" % self.id
return "\n".join([self._xprt(), self._src_reqs(),
self._cong_slots(), self._queues() ])

+ def read_state(self):
+ if self.path.exists():
+ with open(self.path / "xprt_state") as f:
+ self.state = ','.join(f.readline().split()[1:])
+
def small_str(self):
main = " [main]" if self.info.get("main_xprt") else ""
return f"xprt {self.id}: {self.type}, {self.dstaddr}{main}"
@@ -46,6 +51,11 @@ class Xprt:
resolved = socket.gethostbyname(newaddr)
self.dstaddr = sysfs.write_addr_file(self.path / "dstaddr", resolved)

+ def set_state(self, state):
+ with open(self.path / "xprt_state", 'w') as f:
+ f.write(state)
+ self.read_state()
+

def list_xprts(args):
xprts = [ Xprt(f) for f in (sysfs.SUNRPC / "xprt-switches").glob("**/xprt-*") ]
@@ -65,6 +75,13 @@ def set_xprt_property(args):
try:
if args.dstaddr != None:
xprt.set_dstaddr(args.dstaddr[0])
+ if args.offline:
+ xprt.set_state("offline")
+ elif args.online:
+ xprt.set_state("online")
+ elif args.remove:
+ xprt.set_state("offline")
+ xprt.set_state("remove")
print(xprt)
except Exception as e:
print(e)
@@ -78,4 +95,7 @@ def add_command(subparser):
parser = subparser.add_parser("set", help="Set an xprt property")
parser.add_argument("--id", metavar="ID", nargs=1, type=int, required=True, help="Id of a specific xprt to modify")
parser.add_argument("--dstaddr", metavar="dstaddr", nargs=1, type=str, help="New dstaddr to set")
+ parser.add_argument("--offline", action="store_true", help="Set an xprt offline")
+ parser.add_argument("--online", action="store_true", help="Set an offline xprt back online")
+ parser.add_argument("--remove", action="store_true", help="Remove an xprt")
parser.set_defaults(func=set_xprt_property)
--
2.33.1

2021-10-28 18:36:05

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v5 1/9] rpcctl: Add a rpcctl.py tool

From: Anna Schumaker <[email protected]>

This will be used to print and manipulate the sunrpc sysfs directory
files. Running without arguments prints both usage information and the
location of the sunrpc sysfs directory.

Signed-off-by: Anna Schumaker <[email protected]>
---
.gitignore | 2 ++
tools/rpcctl/rpcctl.py | 13 +++++++++++++
tools/rpcctl/sysfs.py | 19 +++++++++++++++++++
3 files changed, 34 insertions(+)
create mode 100755 tools/rpcctl/rpcctl.py
create mode 100644 tools/rpcctl/sysfs.py

diff --git a/.gitignore b/.gitignore
index c89d1cd2583d..a476bd20bc3b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -84,3 +84,5 @@ systemd/rpc-gssd.service
cscope.*
# generic editor backup et al
*~
+# python bytecode
+__pycache__
diff --git a/tools/rpcctl/rpcctl.py b/tools/rpcctl/rpcctl.py
new file mode 100755
index 000000000000..8ff59ea9e81b
--- /dev/null
+++ b/tools/rpcctl/rpcctl.py
@@ -0,0 +1,13 @@
+#!/usr/bin/python
+import argparse
+import sysfs
+
+parser = argparse.ArgumentParser()
+
+def show_small_help(args):
+ parser.print_usage()
+ print("sunrpc dir:", sysfs.SUNRPC)
+parser.set_defaults(func=show_small_help)
+
+args = parser.parse_args()
+args.func(args)
diff --git a/tools/rpcctl/sysfs.py b/tools/rpcctl/sysfs.py
new file mode 100644
index 000000000000..c9d477063585
--- /dev/null
+++ b/tools/rpcctl/sysfs.py
@@ -0,0 +1,19 @@
+import pathlib
+import re
+import sys
+
+MOUNT = None
+with open("/proc/mounts", 'r') as f:
+ for line in f:
+ if re.search("^sys ", line):
+ MOUNT = line.split()[1]
+ break
+
+if MOUNT == None:
+ print("ERROR: sysfs is not mounted")
+ sys.exit(1)
+
+SUNRPC = pathlib.Path(MOUNT) / "kernel" / "sunrpc"
+if not SUNRPC.is_dir():
+ print("ERROR: sysfs does not have sunrpc directory")
+ sys.exit(1)
--
2.33.1

2021-10-28 18:36:05

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v5 2/9] rpcctl: Add a command for printing xprt switch information

From: Anna Schumaker <[email protected]>

This combines the information found in xprt_switch_info with a subset of
the information found in each xprt subdirectory

Signed-off-by: Anna Schumaker <[email protected]>
---
v5: Clean up how the XprtSwitch __str__() function works
Rename the subcommand to simply "switch"
---
tools/rpcctl/rpcctl.py | 6 ++++++
tools/rpcctl/switch.py | 35 +++++++++++++++++++++++++++++++++++
tools/rpcctl/sysfs.py | 18 ++++++++++++++++++
tools/rpcctl/xprt.py | 14 ++++++++++++++
4 files changed, 73 insertions(+)
create mode 100644 tools/rpcctl/switch.py
create mode 100644 tools/rpcctl/xprt.py

diff --git a/tools/rpcctl/rpcctl.py b/tools/rpcctl/rpcctl.py
index 8ff59ea9e81b..90efcbed7ac8 100755
--- a/tools/rpcctl/rpcctl.py
+++ b/tools/rpcctl/rpcctl.py
@@ -9,5 +9,11 @@ def show_small_help(args):
print("sunrpc dir:", sysfs.SUNRPC)
parser.set_defaults(func=show_small_help)

+
+import switch
+subparser = parser.add_subparsers(title="commands")
+switch.add_command(subparser)
+
+
args = parser.parse_args()
args.func(args)
diff --git a/tools/rpcctl/switch.py b/tools/rpcctl/switch.py
new file mode 100644
index 000000000000..c96e70b7710f
--- /dev/null
+++ b/tools/rpcctl/switch.py
@@ -0,0 +1,35 @@
+import sysfs
+import xprt
+
+class XprtSwitch:
+ def __init__(self, path):
+ self.path = path
+ self.id = int(path.stem.split("-")[1])
+ self.info = sysfs.read_info_file(path / "xprt_switch_info")
+
+ self.xprts = [ xprt.Xprt(p) for p in self.path.iterdir() if p.is_dir() ]
+ self.xprts.sort()
+
+ def __lt__(self, rhs):
+ return self.path < rhs.path
+
+ def __str__(self):
+ switch = f"switch {self.id}: " \
+ f"xprts {self.info['num_xprts']}, " \
+ f"active {self.info['num_active']}, " \
+ f"queue {self.info['queue_len']}"
+ xprts = [ f" {x.small_str()}" for x in self.xprts ]
+ return "\n".join([ switch ] + xprts)
+
+
+def list_xprt_switches(args):
+ switches = [ XprtSwitch(f) for f in (sysfs.SUNRPC / "xprt-switches").iterdir() ]
+ switches.sort()
+ for xs in switches:
+ if args.id == None or xs.id == args.id[0]:
+ print(xs)
+
+def add_command(subparser):
+ parser = subparser.add_parser("switch", help="Commands for xprt switches")
+ parser.add_argument("--id", metavar="ID", nargs=1, type=int, help="Id of a specific xprt-switch to show")
+ parser.set_defaults(func=list_xprt_switches)
diff --git a/tools/rpcctl/sysfs.py b/tools/rpcctl/sysfs.py
index c9d477063585..c05d2d591175 100644
--- a/tools/rpcctl/sysfs.py
+++ b/tools/rpcctl/sysfs.py
@@ -1,3 +1,4 @@
+import collections
import pathlib
import re
import sys
@@ -17,3 +18,20 @@ SUNRPC = pathlib.Path(MOUNT) / "kernel" / "sunrpc"
if not SUNRPC.is_dir():
print("ERROR: sysfs does not have sunrpc directory")
sys.exit(1)
+
+
+def read_addr_file(path):
+ try:
+ with open(path, 'r') as f:
+ return f.readline().strip()
+ except:
+ return "(enoent)"
+
+def read_info_file(path):
+ res = collections.defaultdict(int)
+ try:
+ with open(path) as info:
+ lines = [ l.split("=", 1) for l in info if "=" in l ]
+ res.update({ key:int(val.strip()) for (key, val) in lines })
+ finally:
+ return res
diff --git a/tools/rpcctl/xprt.py b/tools/rpcctl/xprt.py
new file mode 100644
index 000000000000..62859a23ea4d
--- /dev/null
+++ b/tools/rpcctl/xprt.py
@@ -0,0 +1,14 @@
+import sysfs
+
+class Xprt:
+ def __init__(self, path):
+ self.path = path
+ self.id = int(path.stem.split("-")[1])
+ self.type = path.stem.split("-")[2]
+ self.dstaddr = sysfs.read_addr_file(path / "dstaddr")
+
+ def __lt__(self, rhs):
+ return self.id < rhs.id
+
+ def small_str(self):
+ return f"xprt {self.id}: {self.type}, {self.dstaddr}"
--
2.33.1

2021-10-28 18:36:07

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v5 9/9] rpcctl: Add installation to the Makefile

From: Anna Schumaker <[email protected]>

And create a shell script that launches the python program from the
$(libdir)

Signed-off-by: Anna Schumaker <[email protected]>
---
configure.ac | 1 +
tools/Makefile.am | 2 +-
tools/rpcctl/Makefile.am | 20 ++++++++++++++++++++
tools/rpcctl/rpcctl | 5 +++++
4 files changed, 27 insertions(+), 1 deletion(-)
create mode 100644 tools/rpcctl/Makefile.am
create mode 100644 tools/rpcctl/rpcctl

diff --git a/configure.ac b/configure.ac
index 93626d62be40..dcd3be0c8a8b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -737,6 +737,7 @@ AC_CONFIG_FILES([
tools/rpcgen/Makefile
tools/mountstats/Makefile
tools/nfs-iostat/Makefile
+ tools/rpcctl/Makefile
tools/nfsdclnts/Makefile
tools/nfsconf/Makefile
tools/nfsdclddb/Makefile
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 9b4b0803db39..c3feabbec681 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -12,6 +12,6 @@ if CONFIG_NFSDCLD
OPTDIRS += nfsdclddb
endif

-SUBDIRS = locktest rpcdebug nlmtest mountstats nfs-iostat nfsdclnts $(OPTDIRS)
+SUBDIRS = locktest rpcdebug nlmtest mountstats nfs-iostat rpcctl nfsdclnts $(OPTDIRS)

MAINTAINERCLEANFILES = Makefile.in
diff --git a/tools/rpcctl/Makefile.am b/tools/rpcctl/Makefile.am
new file mode 100644
index 000000000000..f4237dbc89e5
--- /dev/null
+++ b/tools/rpcctl/Makefile.am
@@ -0,0 +1,20 @@
+## Process this file with automake to produce Makefile.in
+PYTHON_FILES = rpcctl.py client.py switch.py sysfs.py xprt.py
+tooldir = $(DESTDIR)$(libdir)/rpcctl
+
+man8_MANS = rpcctl.man
+
+all-local: $(PYTHON_FILES)
+
+install-data-hook:
+ mkdir -p $(tooldir)
+ for f in $(PYTHON_FILES) ; do \
+ $(INSTALL) -m 644 $$f $(tooldir)/$$f ; \
+ done
+ chmod +x $(tooldir)/rpcctl.py
+ $(INSTALL) -m 755 rpcctl $(DESTDIR)$(sbindir)/rpcctl
+ sed -i "s|LIBDIR=.|LIBDIR=$(tooldir)|" $(DESTDIR)$(sbindir)/rpcctl
+
+
+
+MAINTAINERCLEANFILES=Makefile.in
diff --git a/tools/rpcctl/rpcctl b/tools/rpcctl/rpcctl
new file mode 100644
index 000000000000..4cc35e1ea3f9
--- /dev/null
+++ b/tools/rpcctl/rpcctl
@@ -0,0 +1,5 @@
+#!/bin/bash
+LIBDIR=.
+PYTHON3=/usr/bin/python
+
+exec $PYTHON3 $LIBDIR/rpcctl.py $*
--
2.33.1

2021-11-01 14:41:47

by Chuck Lever III

[permalink] [raw]
Subject: Re: [PATCH v5 0/9] Add a tool for using the new sysfs files



> On Oct 28, 2021, at 2:35 PM, [email protected] wrote:
>
> From: Anna Schumaker <[email protected]>
>
> These patches implement a tool that can be used to read and write the
> sysfs files, with subcommands!
>
> The following subcommands are implemented:
> rpcctl client
> rpcctl switch
> rpcctl switch set
> rpcctl xprt
> rpcctl xprt set
>
> So you can print out information about every switch with:
> anna@client ~ % rpcctl switch
> switch 0: xprts 1, active 1, queue 0
> xprt 0: local, /var/run/gssproxy.sock [main]
> switch 1: xprts 1, active 1, queue 0
> xprt 1: local, /var/run/rpcbind.sock [main]
> switch 2: xprts 1, active 1, queue 0
> xprt 2: tcp, 192.168.111.1 [main]
> switch 3: xprts 4, active 4, queue 0
> xprt 3: tcp, 192.168.111.188 [main]
> xprt 4: tcp, 192.168.111.188
> xprt 5: tcp, 192.168.111.188
> xprt 6: tcp, 192.168.111.188
>
> And information about each xprt:
> anna@client ~ % rpcctl xprt
> xprt 0: local, /var/run/gssproxy.sock, port 0, state <CONNECTED,BOUND>, main
> Source: (einval), port 0, Requests: 2
> Congestion: cur 0, win 256, Slots: min 2, max 65536
> Queues: binding 0, sending 0, pending 0, backlog 0, tasks 0
> xprt 1: local, /var/run/rpcbind.sock, port 0, state <CONNECTED,BOUND>, main
> Source: (einval), port 0, Requests: 2
> Congestion: cur 0, win 256, Slots: min 2, max 65536
> Queues: binding 0, sending 0, pending 0, backlog 0, tasks 0
> xprt 2: tcp, 192.168.111.1, port 2049, state <CONNECTED,BOUND>, main
> Source: 192.168.111.222, port 959, Requests: 2
> Congestion: cur 0, win 256, Slots: min 2, max 65536
> Queues: binding 0, sending 0, pending 0, backlog 0, tasks 0
> xprt 3: tcp, 192.168.111.188, port 2049, state <CONNECTED,BOUND>, main
> Source: 192.168.111.222, port 921, Requests: 2
> Congestion: cur 0, win 256, Slots: min 2, max 65536
> Queues: binding 0, sending 0, pending 0, backlog 0, tasks 0
> xprt 4: tcp, 192.168.111.188, port 2049, state <CONNECTED,BOUND>
> Source: 192.168.111.222, port 726, Requests: 2
> Congestion: cur 0, win 256, Slots: min 2, max 65536
> Queues: binding 0, sending 0, pending 0, backlog 0, tasks 0
> xprt 5: tcp, 192.168.111.188, port 2049, state <CONNECTED,BOUND>
> Source: 192.168.111.222, port 671, Requests: 2
> Congestion: cur 0, win 256, Slots: min 2, max 65536
> Queues: binding 0, sending 0, pending 0, backlog 0, tasks 0
> xprt 6: tcp, 192.168.111.188, port 2049, state <CONNECTED,BOUND>
> Source: 192.168.111.222, port 934, Requests: 2
> Congestion: cur 0, win 256, Slots: min 2, max 65536
> Queues: binding 0, sending 0, pending 0, backlog 0, tasks 0
>
> You can use the `set` subcommand to change the dstaddr of individual xprts:
> anna@client ~ % sudo rpcctl xprt --id 4
> xprt 4: tcp, 192.168.111.188, port 2049, state <CONNECTED,BOUND>
> Source: 192.168.111.222, port 726, Requests: 2
> Congestion: cur 0, win 256, Slots: min 2, max 65536
> Queues: binding 0, sending 0, pending 0, backlog 0, tasks 0
> anna@client ~ % sudo rpcctl xprt set --id 4 --dstaddr server2.nowheycreamery.com
> xprt 4: tcp, 192.168.111.186, port 2049, state <CONNECTED,BOUND>
> Source: 192.168.111.222, port 726, Requests: 2
> Congestion: cur 0, win 256, Slots: min 2, max 65536
> Queues: binding 0, sending 0, pending 0, backlog 0, tasks 0
>
> Or for changing the dstaddr of all xprts attached to a switch:
> anna@client % rpcctl switch --id 3
> switch 3: xprts 4, active 4, queue 0
> xprt 3: tcp, 192.168.111.188 [main]
> xprt 4: tcp, 192.168.111.188
> xprt 5: tcp, 192.168.111.188
> xprt 6: tcp, 192.168.111.188
> anna@client % sudo rpcctl switch set --id 4 --dstaddr server2.nowheycreamery.vm
> switch 3: xprts 4, active 4, queue 0
> xprt 2: tcp, 192.168.111.186 [main]
> xprt 3: tcp, 192.168.111.186
> xprt 5: tcp, 192.168.111.186
> xprt 6: tcp, 192.168.111.186
>
> Changes in v5:
> - Rename from 'rpcctl' to 'rpcctl'
> - Rename subcommands 'xprt-switch" to 'switch' and 'rpc-client' to 'client'
> - Clean up how the displayed strings are generated
> - Handle kernels that don't yet have the srcaddr patch
>
> Thoughts?

LGTM!


> Anna
>
>
> Anna Schumaker (9):
> rpcctl: Add a rpcctl.py tool
> rpcctl: Add a command for printing xprt switch information
> rpcctl: Add a command for printing individual xprts
> rpcctl: Add a command for printing rpc client information
> rpcctl: Add a command for changing xprt dstaddr
> rpcctl: Add a command for changing xprt switch dstaddrs
> rpcctl: Add a command for changing xprt state
> rpcctl: Add a man page
> rpcctl: Add installation to the Makefile
>
> .gitignore | 2 +
> configure.ac | 1 +
> tools/Makefile.am | 2 +-
> tools/rpcctl/Makefile.am | 20 ++++++++
> tools/rpcctl/client.py | 27 +++++++++++
> tools/rpcctl/rpcctl | 5 ++
> tools/rpcctl/rpcctl.man | 88 ++++++++++++++++++++++++++++++++++
> tools/rpcctl/rpcctl.py | 23 +++++++++
> tools/rpcctl/switch.py | 51 ++++++++++++++++++++
> tools/rpcctl/sysfs.py | 42 ++++++++++++++++
> tools/rpcctl/xprt.py | 101 +++++++++++++++++++++++++++++++++++++++
> 11 files changed, 361 insertions(+), 1 deletion(-)
> create mode 100644 tools/rpcctl/Makefile.am
> create mode 100644 tools/rpcctl/client.py
> create mode 100644 tools/rpcctl/rpcctl
> create mode 100644 tools/rpcctl/rpcctl.man
> create mode 100755 tools/rpcctl/rpcctl.py
> create mode 100644 tools/rpcctl/switch.py
> create mode 100644 tools/rpcctl/sysfs.py
> create mode 100644 tools/rpcctl/xprt.py
>
> --
> 2.33.1
>

--
Chuck Lever



2021-11-08 22:07:45

by Steve Dickson

[permalink] [raw]
Subject: Re: [PATCH v5 9/9] rpcctl: Add installation to the Makefile

Hello,

On 10/28/21 14:35, [email protected] wrote:
> From: Anna Schumaker <[email protected]>
>
> And create a shell script that launches the python program from the
> $(libdir)
>
> Signed-off-by: Anna Schumaker <[email protected]>
> ---
> configure.ac | 1 +
> tools/Makefile.am | 2 +-
> tools/rpcctl/Makefile.am | 20 ++++++++++++++++++++
> tools/rpcctl/rpcctl | 5 +++++
> 4 files changed, 27 insertions(+), 1 deletion(-)
> create mode 100644 tools/rpcctl/Makefile.am
> create mode 100644 tools/rpcctl/rpcctl
>
> diff --git a/configure.ac b/configure.ac
> index 93626d62be40..dcd3be0c8a8b 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -737,6 +737,7 @@ AC_CONFIG_FILES([
> tools/rpcgen/Makefile
> tools/mountstats/Makefile
> tools/nfs-iostat/Makefile
> + tools/rpcctl/Makefile
> tools/nfsdclnts/Makefile
> tools/nfsconf/Makefile
> tools/nfsdclddb/Makefile
> diff --git a/tools/Makefile.am b/tools/Makefile.am
> index 9b4b0803db39..c3feabbec681 100644
> --- a/tools/Makefile.am
> +++ b/tools/Makefile.am
> @@ -12,6 +12,6 @@ if CONFIG_NFSDCLD
> OPTDIRS += nfsdclddb
> endif
>
> -SUBDIRS = locktest rpcdebug nlmtest mountstats nfs-iostat nfsdclnts $(OPTDIRS)
> +SUBDIRS = locktest rpcdebug nlmtest mountstats nfs-iostat rpcctl nfsdclnts $(OPTDIRS)
>
> MAINTAINERCLEANFILES = Makefile.in
> diff --git a/tools/rpcctl/Makefile.am b/tools/rpcctl/Makefile.am
> new file mode 100644
> index 000000000000..f4237dbc89e5
> --- /dev/null
> +++ b/tools/rpcctl/Makefile.am
> @@ -0,0 +1,20 @@
> +## Process this file with automake to produce Makefile.in
> +PYTHON_FILES = rpcctl.py client.py switch.py sysfs.py xprt.py
> +tooldir = $(DESTDIR)$(libdir)/rpcctl
> +
> +man8_MANS = rpcctl.man
> +
> +all-local: $(PYTHON_FILES)
> +
> +install-data-hook:
> + mkdir -p $(tooldir)
> + for f in $(PYTHON_FILES) ; do \
> + $(INSTALL) -m 644 $$f $(tooldir)/$$f ; \
> + done
> + chmod +x $(tooldir)/rpcctl.py
> + $(INSTALL) -m 755 rpcctl $(DESTDIR)$(sbindir)/rpcctl
> + sed -i "s|LIBDIR=.|LIBDIR=$(tooldir)|" $(DESTDIR)$(sbindir)/rpcctl
A couple issues here....

* Changing a file after installed breaks rpm process since it
changes the checksum of the file so the process thinks it is
an undeclared file.

* Why is the $(sbindir)/rpcctl wrapper even needed?
Why not simply put the code that is in $(tooldir)/rpcctl.py
in the /usr/sbin/rpcctl?

* It appears the proper place to put .py modules is
under /usr/lib/python-<ver>/rpcctl not /usr/lib64/rpcctl

Finally when I manually set LIBDIR=/usr/lib64/rpcctl in
the /usr/sbin/rpcctl wrapper all I got was
# rpcctl --help
ERROR: sysfs is not mounted

So I know it was seeing sys.py module but not seeing
/sys/kernel/sunrpc/ which does exist.

# ls /sys/kernel/sunrpc/
./ ../ rpc-clients/ xprt-switches/

So my suggestion is get rid of that wrapper
and look under /usr/lib/python-<ver>/rpcctl
for the .py modules.

steved.

> +
> +
> +
> +MAINTAINERCLEANFILES=Makefile.in
> diff --git a/tools/rpcctl/rpcctl b/tools/rpcctl/rpcctl
> new file mode 100644
> index 000000000000..4cc35e1ea3f9
> --- /dev/null
> +++ b/tools/rpcctl/rpcctl
> @@ -0,0 +1,5 @@
> +#!/bin/bash
> +LIBDIR=.
> +PYTHON3=/usr/bin/python
> +
> +exec $PYTHON3 $LIBDIR/rpcctl.py $*
>

2021-11-08 22:10:15

by Steve Dickson

[permalink] [raw]
Subject: Re: [PATCH v5 9/9] rpcctl: Add installation to the Makefile



On 11/8/21 12:15, Steve Dickson wrote:
> Hello,
>
> On 10/28/21 14:35, [email protected] wrote:
>> From: Anna Schumaker <[email protected]>
>>
>> And create a shell script that launches the python program from the
>> $(libdir)
>>
>> Signed-off-by: Anna Schumaker <[email protected]>
>> ---
>>   configure.ac             |  1 +
>>   tools/Makefile.am        |  2 +-
>>   tools/rpcctl/Makefile.am | 20 ++++++++++++++++++++
>>   tools/rpcctl/rpcctl      |  5 +++++
>>   4 files changed, 27 insertions(+), 1 deletion(-)
>>   create mode 100644 tools/rpcctl/Makefile.am
>>   create mode 100644 tools/rpcctl/rpcctl
>>
>> diff --git a/configure.ac b/configure.ac
>> index 93626d62be40..dcd3be0c8a8b 100644
>> --- a/configure.ac
>> +++ b/configure.ac
>> @@ -737,6 +737,7 @@ AC_CONFIG_FILES([
>>       tools/rpcgen/Makefile
>>       tools/mountstats/Makefile
>>       tools/nfs-iostat/Makefile
>> +    tools/rpcctl/Makefile
>>       tools/nfsdclnts/Makefile
>>       tools/nfsconf/Makefile
>>       tools/nfsdclddb/Makefile
>> diff --git a/tools/Makefile.am b/tools/Makefile.am
>> index 9b4b0803db39..c3feabbec681 100644
>> --- a/tools/Makefile.am
>> +++ b/tools/Makefile.am
>> @@ -12,6 +12,6 @@ if CONFIG_NFSDCLD
>>   OPTDIRS += nfsdclddb
>>   endif
>> -SUBDIRS = locktest rpcdebug nlmtest mountstats nfs-iostat nfsdclnts
>> $(OPTDIRS)
>> +SUBDIRS = locktest rpcdebug nlmtest mountstats nfs-iostat rpcctl
>> nfsdclnts $(OPTDIRS)
>>   MAINTAINERCLEANFILES = Makefile.in
>> diff --git a/tools/rpcctl/Makefile.am b/tools/rpcctl/Makefile.am
>> new file mode 100644
>> index 000000000000..f4237dbc89e5
>> --- /dev/null
>> +++ b/tools/rpcctl/Makefile.am
>> @@ -0,0 +1,20 @@
>> +## Process this file with automake to produce Makefile.in
>> +PYTHON_FILES =  rpcctl.py client.py switch.py sysfs.py xprt.py
>> +tooldir = $(DESTDIR)$(libdir)/rpcctl
>> +
>> +man8_MANS = rpcctl.man
>> +
>> +all-local: $(PYTHON_FILES)
>> +
>> +install-data-hook:
>> +    mkdir -p $(tooldir)
>> +    for f in $(PYTHON_FILES) ; do \
>> +        $(INSTALL) -m 644 $$f $(tooldir)/$$f ; \
>> +    done
>> +    chmod +x $(tooldir)/rpcctl.py
>> +    $(INSTALL) -m 755 rpcctl $(DESTDIR)$(sbindir)/rpcctl
>> +    sed -i "s|LIBDIR=.|LIBDIR=$(tooldir)|" $(DESTDIR)$(sbindir)/rpcctl
> A couple issues here....
>
> * Changing a file after installed breaks rpm process since it
>   changes the checksum of the file so the process thinks it is
>   an undeclared file.
>
> * Why is the $(sbindir)/rpcctl wrapper even needed?
>   Why not simply put the code that is in $(tooldir)/rpcctl.py
>   in the /usr/sbin/rpcctl?
>
> * It appears the proper place to put .py modules is
>   under /usr/lib/python-<ver>/rpcctl not /usr/lib64/rpcctl
Correction: under /usr/lib/python-<ver>/site-packages/
>
> Finally when I manually set  LIBDIR=/usr/lib64/rpcctl in
> the /usr/sbin/rpcctl wrapper all I got was
> # rpcctl --help
> ERROR: sysfs is not mounted
>
> So I know it was seeing sys.py module but not seeing
> /sys/kernel/sunrpc/ which does exist.
>
> # ls /sys/kernel/sunrpc/
> ./  ../  rpc-clients/  xprt-switches/
>
> So my suggestion is get rid of that wrapper
> and look under /usr/lib/python-<ver>/rpcctl
The same correction here... under
/usr/lib/python-<ver>/site-packages/rpcctl

steved.
> for the .py modules.
>
> steved.
>
>> +
>> +
>> +
>> +MAINTAINERCLEANFILES=Makefile.in
>> diff --git a/tools/rpcctl/rpcctl b/tools/rpcctl/rpcctl
>> new file mode 100644
>> index 000000000000..4cc35e1ea3f9
>> --- /dev/null
>> +++ b/tools/rpcctl/rpcctl
>> @@ -0,0 +1,5 @@
>> +#!/bin/bash
>> +LIBDIR=.
>> +PYTHON3=/usr/bin/python
>> +
>> +exec $PYTHON3 $LIBDIR/rpcctl.py $*
>>

2021-11-09 00:41:04

by Anna Schumaker

[permalink] [raw]
Subject: Re: [PATCH v5 9/9] rpcctl: Add installation to the Makefile

On Mon, Nov 8, 2021 at 12:19 PM Steve Dickson <[email protected]> wrote:
>
>
>
> On 11/8/21 12:15, Steve Dickson wrote:
> > Hello,
> >
> > On 10/28/21 14:35, [email protected] wrote:
> >> From: Anna Schumaker <[email protected]>
> >>
> >> And create a shell script that launches the python program from the
> >> $(libdir)
> >>
> >> Signed-off-by: Anna Schumaker <[email protected]>
> >> ---
> >> configure.ac | 1 +
> >> tools/Makefile.am | 2 +-
> >> tools/rpcctl/Makefile.am | 20 ++++++++++++++++++++
> >> tools/rpcctl/rpcctl | 5 +++++
> >> 4 files changed, 27 insertions(+), 1 deletion(-)
> >> create mode 100644 tools/rpcctl/Makefile.am
> >> create mode 100644 tools/rpcctl/rpcctl
> >>
> >> diff --git a/configure.ac b/configure.ac
> >> index 93626d62be40..dcd3be0c8a8b 100644
> >> --- a/configure.ac
> >> +++ b/configure.ac
> >> @@ -737,6 +737,7 @@ AC_CONFIG_FILES([
> >> tools/rpcgen/Makefile
> >> tools/mountstats/Makefile
> >> tools/nfs-iostat/Makefile
> >> + tools/rpcctl/Makefile
> >> tools/nfsdclnts/Makefile
> >> tools/nfsconf/Makefile
> >> tools/nfsdclddb/Makefile
> >> diff --git a/tools/Makefile.am b/tools/Makefile.am
> >> index 9b4b0803db39..c3feabbec681 100644
> >> --- a/tools/Makefile.am
> >> +++ b/tools/Makefile.am
> >> @@ -12,6 +12,6 @@ if CONFIG_NFSDCLD
> >> OPTDIRS += nfsdclddb
> >> endif
> >> -SUBDIRS = locktest rpcdebug nlmtest mountstats nfs-iostat nfsdclnts
> >> $(OPTDIRS)
> >> +SUBDIRS = locktest rpcdebug nlmtest mountstats nfs-iostat rpcctl
> >> nfsdclnts $(OPTDIRS)
> >> MAINTAINERCLEANFILES = Makefile.in
> >> diff --git a/tools/rpcctl/Makefile.am b/tools/rpcctl/Makefile.am
> >> new file mode 100644
> >> index 000000000000..f4237dbc89e5
> >> --- /dev/null
> >> +++ b/tools/rpcctl/Makefile.am
> >> @@ -0,0 +1,20 @@
> >> +## Process this file with automake to produce Makefile.in
> >> +PYTHON_FILES = rpcctl.py client.py switch.py sysfs.py xprt.py
> >> +tooldir = $(DESTDIR)$(libdir)/rpcctl
> >> +
> >> +man8_MANS = rpcctl.man
> >> +
> >> +all-local: $(PYTHON_FILES)
> >> +
> >> +install-data-hook:
> >> + mkdir -p $(tooldir)
> >> + for f in $(PYTHON_FILES) ; do \
> >> + $(INSTALL) -m 644 $$f $(tooldir)/$$f ; \
> >> + done
> >> + chmod +x $(tooldir)/rpcctl.py
> >> + $(INSTALL) -m 755 rpcctl $(DESTDIR)$(sbindir)/rpcctl
> >> + sed -i "s|LIBDIR=.|LIBDIR=$(tooldir)|" $(DESTDIR)$(sbindir)/rpcctl
> > A couple issues here....
> >
> > * Changing a file after installed breaks rpm process since it
> > changes the checksum of the file so the process thinks it is
> > an undeclared file.
> >
> > * Why is the $(sbindir)/rpcctl wrapper even needed?
> > Why not simply put the code that is in $(tooldir)/rpcctl.py
> > in the /usr/sbin/rpcctl?
> >
> > * It appears the proper place to put .py modules is
> > under /usr/lib/python-<ver>/rpcctl not /usr/lib64/rpcctl
> Correction: under /usr/lib/python-<ver>/site-packages/

Sure

> >
> > Finally when I manually set LIBDIR=/usr/lib64/rpcctl in
> > the /usr/sbin/rpcctl wrapper all I got was
> > # rpcctl --help
> > ERROR: sysfs is not mounted
> >
> > So I know it was seeing sys.py module but not seeing
> > /sys/kernel/sunrpc/ which does exist.
> >
> > # ls /sys/kernel/sunrpc/
> > ./ ../ rpc-clients/ xprt-switches/
> >
> > So my suggestion is get rid of that wrapper
> > and look under /usr/lib/python-<ver>/rpcctl
> The same correction here... under
> /usr/lib/python-<ver>/site-packages/rpcctl

Okay, I will try all that. Thanks for looking it over!

Anna
>
> steved.
> > for the .py modules.
> >
> > steved.
> >
> >> +
> >> +
> >> +
> >> +MAINTAINERCLEANFILES=Makefile.in
> >> diff --git a/tools/rpcctl/rpcctl b/tools/rpcctl/rpcctl
> >> new file mode 100644
> >> index 000000000000..4cc35e1ea3f9
> >> --- /dev/null
> >> +++ b/tools/rpcctl/rpcctl
> >> @@ -0,0 +1,5 @@
> >> +#!/bin/bash
> >> +LIBDIR=.
> >> +PYTHON3=/usr/bin/python
> >> +
> >> +exec $PYTHON3 $LIBDIR/rpcctl.py $*
> >>
>