From patchwork Tue Feb 15 19:21:42 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Schumaker, Anna" X-Patchwork-Id: 12747538 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 13099C433EF for ; Tue, 15 Feb 2022 19:21:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237486AbiBOTWE (ORCPT ); Tue, 15 Feb 2022 14:22:04 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:56728 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231234AbiBOTWD (ORCPT ); Tue, 15 Feb 2022 14:22:03 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 83DC977A9B for ; Tue, 15 Feb 2022 11:21:53 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 20CE26179B for ; Tue, 15 Feb 2022 19:21:53 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3D880C340F0; Tue, 15 Feb 2022 19:21:52 +0000 (UTC) From: Anna.Schumaker@Netapp.com To: steved@redhat.com, linux-nfs@vger.kernel.org Cc: Anna.Schumaker@Netapp.com Subject: [PATCH v8 1/9] rpcctl: Add a rpcctl.py tool Date: Tue, 15 Feb 2022 14:21:42 -0500 Message-Id: <20220215192150.53811-2-Anna.Schumaker@Netapp.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220215192150.53811-1-Anna.Schumaker@Netapp.com> References: <20220215192150.53811-1-Anna.Schumaker@Netapp.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org From: Anna Schumaker 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 --- tools/rpcctl/rpcctl.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100755 tools/rpcctl/rpcctl.py diff --git a/tools/rpcctl/rpcctl.py b/tools/rpcctl/rpcctl.py new file mode 100755 index 000000000000..9737ac4a9740 --- /dev/null +++ b/tools/rpcctl/rpcctl.py @@ -0,0 +1,25 @@ +#!/usr/bin/python3 +import argparse +import pathlib +import sys + +with open("/proc/mounts", 'r') as f: + mount = [ line.split()[1] for line in f if "sysfs" in line ] + if len(mount) == 0: + print("ERROR: sysfs is not mounted") + sys.exit(1) + +sunrpc = pathlib.Path(mount[0]) / "kernel" / "sunrpc" +if not sunrpc.is_dir(): + print("ERROR: sysfs does not have sunrpc directory") + sys.exit(1) + +parser = argparse.ArgumentParser() + +def show_small_help(args): + parser.print_usage() + print("sunrpc dir:", sunrpc) +parser.set_defaults(func=show_small_help) + +args = parser.parse_args() +args.func(args) From patchwork Tue Feb 15 19:21:43 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Schumaker, Anna" X-Patchwork-Id: 12747539 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8AF11C433FE for ; Tue, 15 Feb 2022 19:21:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237918AbiBOTWF (ORCPT ); Tue, 15 Feb 2022 14:22:05 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:56748 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231234AbiBOTWE (ORCPT ); Tue, 15 Feb 2022 14:22:04 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0A91278064 for ; Tue, 15 Feb 2022 11:21:54 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 9965D6179D for ; Tue, 15 Feb 2022 19:21:53 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id BF6A3C340F2; Tue, 15 Feb 2022 19:21:52 +0000 (UTC) From: Anna.Schumaker@Netapp.com To: steved@redhat.com, linux-nfs@vger.kernel.org Cc: Anna.Schumaker@Netapp.com Subject: [PATCH v8 2/9] rpcctl: Add a command for printing xprt switch information Date: Tue, 15 Feb 2022 14:21:43 -0500 Message-Id: <20220215192150.53811-3-Anna.Schumaker@Netapp.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220215192150.53811-1-Anna.Schumaker@Netapp.com> References: <20220215192150.53811-1-Anna.Schumaker@Netapp.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org From: Anna Schumaker 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 --- v8: Handle Exceptions when running commands --- tools/rpcctl/rpcctl.py | 80 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 1 deletion(-) diff --git a/tools/rpcctl/rpcctl.py b/tools/rpcctl/rpcctl.py index 9737ac4a9740..1eb0454aaf58 100755 --- a/tools/rpcctl/rpcctl.py +++ b/tools/rpcctl/rpcctl.py @@ -1,5 +1,6 @@ #!/usr/bin/python3 import argparse +import collections import pathlib import sys @@ -14,6 +15,76 @@ 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 + + +class Xprt: + def __init__(self, path): + self.path = path + self.name = path.stem.rsplit("-", 1)[0] + self.type = path.stem.split("-")[2] + self.dstaddr = read_addr_file(path / "dstaddr") + + def __lt__(self, rhs): + return self.name < rhs.name + + def small_str(self): + return f"{self.name}: {self.type}, {self.dstaddr}" + + +class XprtSwitch: + def __init__(self, path): + self.path = path + self.name = path.stem + self.info = read_info_file(path / "xprt_switch_info") + self.xprts = sorted([ Xprt(p) for p in self.path.iterdir() if p.is_dir() ]) + + def __lt__(self, rhs): + return self.name < rhs.name + + def __str__(self): + switch = f"{self.name}: " \ + 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 add_command(subparser): + parser = subparser.add_parser("switch", help="Commands for xprt switches") + parser.set_defaults(func=XprtSwitch.show, switch=None) + subparser = parser.add_subparsers() + + show = subparser.add_parser("show", help="Show xprt switches") + show.add_argument("switch", metavar="SWITCH", nargs='?', + help="Name of a specific switch to show") + show.set_defaults(func=XprtSwitch.show) + + def get_by_name(name): + xprt_switches = sunrpc / "xprt-switches" + if name: + return [ XprtSwitch(xprt_switches / name) ] + return [ XprtSwitch(f) for f in sorted(xprt_switches.iterdir()) ] + + def show(args): + for switch in XprtSwitch.get_by_name(args.switch): + print(switch) + + parser = argparse.ArgumentParser() def show_small_help(args): @@ -21,5 +92,12 @@ def show_small_help(args): print("sunrpc dir:", sunrpc) parser.set_defaults(func=show_small_help) +subparser = parser.add_subparsers(title="commands") +XprtSwitch.add_command(subparser) + args = parser.parse_args() -args.func(args) +try: + args.func(args) +except Exception as e: + print(str(e)) + sys.exit(1) From patchwork Tue Feb 15 19:21:44 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Schumaker, Anna" X-Patchwork-Id: 12747542 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5B298C43217 for ; Tue, 15 Feb 2022 19:21:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231234AbiBOTWH (ORCPT ); Tue, 15 Feb 2022 14:22:07 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:56774 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239427AbiBOTWG (ORCPT ); Tue, 15 Feb 2022 14:22:06 -0500 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 30B3D78064 for ; Tue, 15 Feb 2022 11:21:56 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id BE47EB81C11 for ; Tue, 15 Feb 2022 19:21:54 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4B05EC340EC; Tue, 15 Feb 2022 19:21:53 +0000 (UTC) From: Anna.Schumaker@Netapp.com To: steved@redhat.com, linux-nfs@vger.kernel.org Cc: Anna.Schumaker@Netapp.com Subject: [PATCH v8 3/9] rpcctl: Add a command for printing individual xprts Date: Tue, 15 Feb 2022 14:21:44 -0500 Message-Id: <20220215192150.53811-4-Anna.Schumaker@Netapp.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220215192150.53811-1-Anna.Schumaker@Netapp.com> References: <20220215192150.53811-1-Anna.Schumaker@Netapp.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org From: Anna Schumaker This shows more detailed information than what is presented with xprt switches. I take the chance to add a main-export indicator to the small_str() used when printing out xprt-switches. Signed-off-by: Anna Schumaker --- v8: Better exception handling if an Xprt isn't found --- tools/rpcctl/rpcctl.py | 55 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/tools/rpcctl/rpcctl.py b/tools/rpcctl/rpcctl.py index 1eb0454aaf58..6b9627318949 100755 --- a/tools/rpcctl/rpcctl.py +++ b/tools/rpcctl/rpcctl.py @@ -1,6 +1,8 @@ #!/usr/bin/python3 import argparse import collections +import errno +import os import pathlib import sys @@ -37,13 +39,63 @@ class Xprt: self.path = path self.name = path.stem.rsplit("-", 1)[0] self.type = path.stem.split("-")[2] + self.info = read_info_file(path / "xprt_info") self.dstaddr = read_addr_file(path / "dstaddr") + self.srcaddr = read_addr_file(path / "srcaddr") + + with open(path / "xprt_state") as f: + self.state = ','.join(f.readline().split()[1:]) def __lt__(self, rhs): return self.name < rhs.name + def _xprt(self): + main = ", main" if self.info.get("main_xprt") else "" + return f"{self.name}: {self.type}, {self.dstaddr}, " \ + f"port {self.info['dst_port']}, state <{self.state}>{main}" + + def _src_reqs(self): + return f" Source: {self.srcaddr}, port {self.info['src_port']}, " \ + f"Requests: {self.info['num_reqs']}" + + def _cong_slots(self): + return f" Congestion: cur {self.info['cur_cong']}, win {self.info['cong_win']}, " \ + f"Slots: min {self.info['min_num_slots']}, max {self.info['max_num_slots']}" + + def _queues(self): + return f" Queues: binding {self.info['binding_q_len']}, " \ + f"sending {self.info['sending_q_len']}, pending {self.info['pending_q_len']}, " \ + f"backlog {self.info['backlog_q_len']}, tasks {self.info['tasks_queuelen']}" + + def __str__(self): + return "\n".join([self._xprt(), self._src_reqs(), + self._cong_slots(), self._queues() ]) + def small_str(self): - return f"{self.name}: {self.type}, {self.dstaddr}" + main = " [main]" if self.info.get("main_xprt") else "" + return f"{self.name}: {self.type}, {self.dstaddr}{main}" + + def add_command(subparser): + parser = subparser.add_parser("xprt", help="Commands for individual xprts") + parser.set_defaults(func=Xprt.show, xprt=None) + subparser = parser.add_subparsers() + + show = subparser.add_parser("show", help="Show xprts") + show.add_argument("xprt", metavar="XPRT", nargs='?', + help="Name of a specific xprt to show") + show.set_defaults(func=Xprt.show) + + def get_by_name(name): + glob = f"**/{name}-*" if name else "**/xprt-*" + res = [ Xprt(x) for x in (sunrpc / "xprt-switches").glob(glob) ] + if name and len(res) == 0: + raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), + f"{sunrpc / 'xprt-switches' / glob}") + return sorted(res) + + def show(args): + for xprt in Xprt.get_by_name(args.xprt): + print(xprt) class XprtSwitch: @@ -94,6 +146,7 @@ parser.set_defaults(func=show_small_help) subparser = parser.add_subparsers(title="commands") XprtSwitch.add_command(subparser) +Xprt.add_command(subparser) args = parser.parse_args() try: From patchwork Tue Feb 15 19:21:45 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Schumaker, Anna" X-Patchwork-Id: 12747540 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id DF0BCC4332F for ; Tue, 15 Feb 2022 19:21:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239151AbiBOTWF (ORCPT ); Tue, 15 Feb 2022 14:22:05 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:56754 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238282AbiBOTWF (ORCPT ); Tue, 15 Feb 2022 14:22:05 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AA3E679C41 for ; Tue, 15 Feb 2022 11:21:54 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 4828061793 for ; Tue, 15 Feb 2022 19:21:54 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id CA9C9C340EB; Tue, 15 Feb 2022 19:21:53 +0000 (UTC) From: Anna.Schumaker@Netapp.com To: steved@redhat.com, linux-nfs@vger.kernel.org Cc: Anna.Schumaker@Netapp.com Subject: [PATCH v8 4/9] rpcctl: Add a command for printing rpc client information Date: Tue, 15 Feb 2022 14:21:45 -0500 Message-Id: <20220215192150.53811-5-Anna.Schumaker@Netapp.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220215192150.53811-1-Anna.Schumaker@Netapp.com> References: <20220215192150.53811-1-Anna.Schumaker@Netapp.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org From: Anna Schumaker 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 --- v8: Better exception handling if an RpcClient isn't found --- tools/rpcctl/rpcctl.py | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/tools/rpcctl/rpcctl.py b/tools/rpcctl/rpcctl.py index 6b9627318949..2e710b5627f0 100755 --- a/tools/rpcctl/rpcctl.py +++ b/tools/rpcctl/rpcctl.py @@ -99,17 +99,18 @@ class Xprt: class XprtSwitch: - def __init__(self, path): + def __init__(self, path, sep=":"): self.path = path self.name = path.stem self.info = read_info_file(path / "xprt_switch_info") self.xprts = sorted([ Xprt(p) for p in self.path.iterdir() if p.is_dir() ]) + self.sep = sep def __lt__(self, rhs): return self.name < rhs.name def __str__(self): - switch = f"{self.name}: " \ + switch = f"{self.name}{self.sep} " \ f"xprts {self.info['num_xprts']}, " \ f"active {self.info['num_active']}, " \ f"queue {self.info['queue_len']}" @@ -137,6 +138,39 @@ class XprtSwitch: print(switch) +class RpcClient: + def __init__(self, path): + self.path = path + self.name = path.stem + self.switch = XprtSwitch(path / (path / "switch").readlink(), sep=",") + + def __lt__(self, rhs): + return self.name < rhs.name + + def __str__(self): + return f"{self.name}: {self.switch}" + + def add_command(subparser): + parser = subparser.add_parser("client", help="Commands for rpc clients") + parser.set_defaults(func=RpcClient.show, client=None) + subparser = parser.add_subparsers() + + show = subparser.add_parser("show", help="Show rpc clients") + show.add_argument("client", metavar="CLIENT", nargs='?', + help="Name of a specific rpc client to show") + parser.set_defaults(func=RpcClient.show) + + def get_by_name(name): + rpc_clients = sunrpc / "rpc-clients" + if name: + return [ RpcClient(rpc_clients / name) ] + return [ RpcClient(f) for f in sorted(rpc_clients.iterdir()) ] + + def show(args): + for client in RpcClient.get_by_name(args.client): + print(client) + + parser = argparse.ArgumentParser() def show_small_help(args): @@ -145,6 +179,7 @@ def show_small_help(args): parser.set_defaults(func=show_small_help) subparser = parser.add_subparsers(title="commands") +RpcClient.add_command(subparser) XprtSwitch.add_command(subparser) Xprt.add_command(subparser) From patchwork Tue Feb 15 19:21:46 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Schumaker, Anna" X-Patchwork-Id: 12747541 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 831D4C433EF for ; Tue, 15 Feb 2022 19:21:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238282AbiBOTWG (ORCPT ); Tue, 15 Feb 2022 14:22:06 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:56756 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238383AbiBOTWF (ORCPT ); Tue, 15 Feb 2022 14:22:05 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 396CE78064 for ; Tue, 15 Feb 2022 11:21:55 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id CA448617C3 for ; Tue, 15 Feb 2022 19:21:54 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 57010C340F0; Tue, 15 Feb 2022 19:21:54 +0000 (UTC) From: Anna.Schumaker@Netapp.com To: steved@redhat.com, linux-nfs@vger.kernel.org Cc: Anna.Schumaker@Netapp.com Subject: [PATCH v8 5/9] rpcctl: Add a command for changing xprt dstaddr Date: Tue, 15 Feb 2022 14:21:46 -0500 Message-Id: <20220215192150.53811-6-Anna.Schumaker@Netapp.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220215192150.53811-1-Anna.Schumaker@Netapp.com> References: <20220215192150.53811-1-Anna.Schumaker@Netapp.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org From: Anna Schumaker Using the socket module for dns resolution Signed-off-by: Anna Schumaker --- tools/rpcctl/rpcctl.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tools/rpcctl/rpcctl.py b/tools/rpcctl/rpcctl.py index 2e710b5627f0..98e1f680ed72 100755 --- a/tools/rpcctl/rpcctl.py +++ b/tools/rpcctl/rpcctl.py @@ -4,6 +4,7 @@ import collections import errno import os import pathlib +import socket import sys with open("/proc/mounts", 'r') as f: @@ -24,6 +25,11 @@ def read_addr_file(path): except: return "(enoent)" +def write_addr_file(path, newaddr): + with open(path, 'w') as f: + f.write(newaddr) + return read_addr_file(path) + def read_info_file(path): res = collections.defaultdict(int) try: @@ -75,6 +81,10 @@ class Xprt: main = " [main]" if self.info.get("main_xprt") else "" return f"{self.name}: {self.type}, {self.dstaddr}{main}" + def set_dstaddr(self, newaddr): + resolved = socket.gethostbyname(newaddr) + self.dstaddr = write_addr_file(self.path / "dstaddr", newaddr) + def add_command(subparser): parser = subparser.add_parser("xprt", help="Commands for individual xprts") parser.set_defaults(func=Xprt.show, xprt=None) @@ -85,6 +95,15 @@ class Xprt: help="Name of a specific xprt to show") show.set_defaults(func=Xprt.show) + set = subparser.add_parser("set", help="Change an xprt property") + set.add_argument("xprt", metavar="XPRT", nargs=1, + help="Name of a specific xprt to modify") + subparser = set.add_subparsers(required=True) + dstaddr = subparser.add_parser("dstaddr", help="Change an xprt's dstaddr") + dstaddr.add_argument("newaddr", metavar="NEWADDR", nargs=1, + help="The new address for the xprt") + dstaddr.set_defaults(func=Xprt.set_property, property="dstaddr") + def get_by_name(name): glob = f"**/{name}-*" if name else "**/xprt-*" res = [ Xprt(x) for x in (sunrpc / "xprt-switches").glob(glob) ] @@ -97,6 +116,12 @@ class Xprt: for xprt in Xprt.get_by_name(args.xprt): print(xprt) + def set_property(args): + for xprt in Xprt.get_by_name(args.xprt[0]): + if args.property == "dstaddr": + xprt.set_dstaddr(socket.gethostbyname(args.newaddr[0])) + print(xprt) + class XprtSwitch: def __init__(self, path, sep=":"): From patchwork Tue Feb 15 19:21:47 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Schumaker, Anna" X-Patchwork-Id: 12747544 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 44E02C433FE for ; Tue, 15 Feb 2022 19:22:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239773AbiBOTWI (ORCPT ); Tue, 15 Feb 2022 14:22:08 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:56784 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239247AbiBOTWH (ORCPT ); Tue, 15 Feb 2022 14:22:07 -0500 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C4CCC77A9B for ; Tue, 15 Feb 2022 11:21:57 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 78A98B81C6F for ; Tue, 15 Feb 2022 19:21:56 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id D920BC340EB; Tue, 15 Feb 2022 19:21:54 +0000 (UTC) From: Anna.Schumaker@Netapp.com To: steved@redhat.com, linux-nfs@vger.kernel.org Cc: Anna.Schumaker@Netapp.com Subject: [PATCH v8 6/9] rpcctl: Add a command for changing xprt switch dstaddrs Date: Tue, 15 Feb 2022 14:21:47 -0500 Message-Id: <20220215192150.53811-7-Anna.Schumaker@Netapp.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220215192150.53811-1-Anna.Schumaker@Netapp.com> References: <20220215192150.53811-1-Anna.Schumaker@Netapp.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org From: Anna Schumaker 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 --- v8: Only call socket.gethostbyname() once instead of for each xprt --- tools/rpcctl/rpcctl.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/tools/rpcctl/rpcctl.py b/tools/rpcctl/rpcctl.py index 98e1f680ed72..0fbce99fff5b 100755 --- a/tools/rpcctl/rpcctl.py +++ b/tools/rpcctl/rpcctl.py @@ -82,7 +82,6 @@ class Xprt: return f"{self.name}: {self.type}, {self.dstaddr}{main}" def set_dstaddr(self, newaddr): - resolved = socket.gethostbyname(newaddr) self.dstaddr = write_addr_file(self.path / "dstaddr", newaddr) def add_command(subparser): @@ -152,6 +151,15 @@ class XprtSwitch: help="Name of a specific switch to show") show.set_defaults(func=XprtSwitch.show) + set = subparser.add_parser("set", help="Change an xprt switch property") + set.add_argument("switch", metavar="SWITCH", nargs=1, + help="Name of a specific xprt switch to modify") + subparser = set.add_subparsers(required=True) + dstaddr = subparser.add_parser("dstaddr", help="Change an xprt switch's dstaddr") + dstaddr.add_argument("newaddr", metavar="NEWADDR", nargs=1, + help="The new address for the xprt switch") + dstaddr.set_defaults(func=XprtSwitch.set_property, property="dstaddr") + def get_by_name(name): xprt_switches = sunrpc / "xprt-switches" if name: @@ -162,6 +170,13 @@ class XprtSwitch: for switch in XprtSwitch.get_by_name(args.switch): print(switch) + def set_property(args): + for switch in XprtSwitch.get_by_name(args.switch[0]): + resolved = socket.gethostbyname(args.newaddr[0]) + for xprt in switch.xprts: + xprt.set_dstaddr(resolved) + print(switch) + class RpcClient: def __init__(self, path): From patchwork Tue Feb 15 19:21:48 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Schumaker, Anna" X-Patchwork-Id: 12747545 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4A12BC433F5 for ; Tue, 15 Feb 2022 19:22:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240215AbiBOTWK (ORCPT ); Tue, 15 Feb 2022 14:22:10 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:56802 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239959AbiBOTWJ (ORCPT ); Tue, 15 Feb 2022 14:22:09 -0500 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 760D178064 for ; Tue, 15 Feb 2022 11:21:58 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 24B38B81C69 for ; Tue, 15 Feb 2022 19:21:57 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6A7AFC340EC; Tue, 15 Feb 2022 19:21:55 +0000 (UTC) From: Anna.Schumaker@Netapp.com To: steved@redhat.com, linux-nfs@vger.kernel.org Cc: Anna.Schumaker@Netapp.com Subject: [PATCH v8 7/9] rpcctl: Add a command for changing xprt state Date: Tue, 15 Feb 2022 14:21:48 -0500 Message-Id: <20220215192150.53811-8-Anna.Schumaker@Netapp.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220215192150.53811-1-Anna.Schumaker@Netapp.com> References: <20220215192150.53811-1-Anna.Schumaker@Netapp.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org From: Anna Schumaker 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 --- tools/rpcctl/rpcctl.py | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/tools/rpcctl/rpcctl.py b/tools/rpcctl/rpcctl.py index 0fbce99fff5b..b8df556b682c 100755 --- a/tools/rpcctl/rpcctl.py +++ b/tools/rpcctl/rpcctl.py @@ -48,9 +48,7 @@ class Xprt: self.info = read_info_file(path / "xprt_info") self.dstaddr = read_addr_file(path / "dstaddr") self.srcaddr = 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.name < rhs.name @@ -74,9 +72,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"{self.name}: has been removed" 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"{self.name}: {self.type}, {self.dstaddr}{main}" @@ -84,11 +89,21 @@ class Xprt: def set_dstaddr(self, newaddr): self.dstaddr = write_addr_file(self.path / "dstaddr", newaddr) + def set_state(self, state): + with open(self.path / "xprt_state", 'w') as f: + f.write(state) + self.read_state() + def add_command(subparser): parser = subparser.add_parser("xprt", help="Commands for individual xprts") parser.set_defaults(func=Xprt.show, xprt=None) subparser = parser.add_subparsers() + remove = subparser.add_parser("remove", help="Remove an xprt") + remove.add_argument("xprt", metavar="XPRT", nargs=1, + help="Name of the xprt to remove") + remove.set_defaults(func=Xprt.set_property, property="remove") + show = subparser.add_parser("show", help="Show xprts") show.add_argument("xprt", metavar="XPRT", nargs='?', help="Name of a specific xprt to show") @@ -98,6 +113,10 @@ class Xprt: set.add_argument("xprt", metavar="XPRT", nargs=1, help="Name of a specific xprt to modify") subparser = set.add_subparsers(required=True) + online = subparser.add_parser("online", help="Set an xprt online") + online.set_defaults(func=Xprt.set_property, property="online") + offline = subparser.add_parser("offline", help="Set an xprt offline") + offline.set_defaults(func=Xprt.set_property, property="offline") dstaddr = subparser.add_parser("dstaddr", help="Change an xprt's dstaddr") dstaddr.add_argument("newaddr", metavar="NEWADDR", nargs=1, help="The new address for the xprt") @@ -119,6 +138,11 @@ class Xprt: for xprt in Xprt.get_by_name(args.xprt[0]): if args.property == "dstaddr": xprt.set_dstaddr(socket.gethostbyname(args.newaddr[0])) + elif args.property == "remove": + xprt.set_state("offline") + xprt.set_state("remove") + else: + args.set_state(args.property) print(xprt) From patchwork Tue Feb 15 19:21:49 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Schumaker, Anna" X-Patchwork-Id: 12747546 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C396FC4332F for ; Tue, 15 Feb 2022 19:22:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239247AbiBOTWK (ORCPT ); Tue, 15 Feb 2022 14:22:10 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:56804 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240165AbiBOTWJ (ORCPT ); Tue, 15 Feb 2022 14:22:09 -0500 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E6CB477A9B for ; Tue, 15 Feb 2022 11:21:58 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 991E2B81C82 for ; Tue, 15 Feb 2022 19:21:57 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id EFED8C340F0; Tue, 15 Feb 2022 19:21:55 +0000 (UTC) From: Anna.Schumaker@Netapp.com To: steved@redhat.com, linux-nfs@vger.kernel.org Cc: Anna.Schumaker@Netapp.com Subject: [PATCH v8 8/9] rpcctl: Add a man page Date: Tue, 15 Feb 2022 14:21:49 -0500 Message-Id: <20220215192150.53811-9-Anna.Schumaker@Netapp.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220215192150.53811-1-Anna.Schumaker@Netapp.com> References: <20220215192150.53811-1-Anna.Schumaker@Netapp.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org From: Anna Schumaker Signed-off-by: Anna Schumaker --- v8: Updates for the new command structure Add examples --- tools/rpcctl/rpcctl.man | 67 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 tools/rpcctl/rpcctl.man diff --git a/tools/rpcctl/rpcctl.man b/tools/rpcctl/rpcctl.man new file mode 100644 index 000000000000..b87ba0df41c0 --- /dev/null +++ b/tools/rpcctl/rpcctl.man @@ -0,0 +1,67 @@ +.\" +.\" rpcctl(8) +.\" +.TH rpcctl 8 "15 Feb 2022" +.SH NAME +rpcctl \- Displays SunRPC connection information +.SH SYNOPSIS +.nf +.BR rpcctl " [ \fB\-h \fR| \fB\-\-help \fR] { \fBclient \fR| \fBswitch \fR| \fBxprt \fR}" +.P +.BR "rpcctl client" " \fR[ \fB\-h \fR| \fB\-\-help \fR] { \fBshow \fR}" +.BR "rpcctl client show " "\fR[ \fB\-h \f| \fB\-\-help \fR] [ \fIXPRT \fR]" +.P +.BR "rpcctl switch" " \fR[ \fB\-h \fR| \fB\-\-help \fR] { \fBset \fR| \fBshow \fR}" +.BR "rpcctl switch set" " \fR[ \fB\-h \fR| \fB\-\-help \fR] \fISWITCH \fBdstaddr \fINEWADDR" +.BR "rpcctl switch show" " \fR[ \fB\-h \fR| \fB\-\-help \fR] [ \fISWITCH \fR]" +.P +.BR "rpcctl xprt" " \fR[ \fB\-h \fR| \fB\-\-help \fR] { \fBremove \fR| \fBset \fR| \fBshow \fR}" +.BR "rpcctl xprt remove" " \fR[ \fB\-h \fR| \fB\-\-help \fR] \fIXPRT" +.BR "rpcctl xprt set" " \fR[ \fB\-h \fR| \fB\-\-help \fR] \fIXPRT \fR{ \fBdstaddr \fINEWADDR \fR| \fBoffline \fR| \fBonline \fR}" +.BR "rpcctl xprt show" " \fR[ \fB\-h \fR| \fB\-\-help \fR] [ \fIXPRT \fR]" +.fi +.SH DESCRIPTION +.RB "The " rpcctl " command displays information collected in the SunRPC sysfs files about the system's SunRPC objects. +.P +.SS rpcctl client \fR- \fBCommands operating on RPC clients +.IP "\fBshow \fR[ \fICLIENT \fR] \fB(default)" +Show detailed information about the RPC clients on this system. +If \fICLIENT \fRwas provided, then only show information about a single RPC client. +.P +.SS rpcctl switch \fR- \fBCommands operating on groups of transports +.IP "\fBset \fISWITCH \fBdstaddr \fINEWADDR" +Change the destination address of all transports in the \fISWITCH \fRto \fINEWADDR\fR. +\fINEWADDR \fRcan be an IP address, DNS name, or anything else resolvable by \fBgethostbyname\fR(3). +.IP "\fBshow \fR[ \fISWITCH \fR] \fB(default)" +Show detailed information about groups of transports on this system. +If \fISWITCH \fRwas provided, then only show information about a single transport group. +.P +.SS rpcctl xprt \fR- \fBCommands operating on individual transports +.IP "\fBremove \fIXPRT" +Removes the specified \fIXPRT \fRfrom the system. +Note that "main" transports cannot be removed. +.P +.IP "\fBset \fIXPRT \fBdstaddr \fINEWADDR" +Change the destination address of the specified \fIXPRT \fR to \fINEWADDR\fR. +\fINEWADDR \fRcan be an IP address, DNS name, or anything else resolvable by \fBgethostbyname\fR(3). +.P +.IP "\fBset \fIXPRT \fBoffline" +Sets the specified \fIXPRT\fR's state to offline. +.P +.IP "\fBset \fIXPRT \fBonline" +Sets the specified \fIXPRT\fR's state to online. +.IP "\fBshow \fR[ \fIXPRT \fR] \fB(default)" +Show detailed information about this system's transports. +If \fIXPRT \fRwas provided, then only show information about a single transport. +.SH EXAMPLES +.IP "\fBrpcctl switch show switch-2" +Show details about the RPC switch named "switch-2". +.IP "\fBrpcctl xprt remove xprt-4" +Remove the xprt named "xprt-4" from the system. +.IP "\fBrpcctl xprt set xprt-3 dstaddr https://linux-nfs.org +Change the dstaddr of the xprt named "xprt-3" to point to linux-nfs.org +.SH DIRECTORY +.TP +.B /sys/kernel/sunrpc/ +.SH AUTHOR +Anna Schumaker From patchwork Tue Feb 15 19:21:50 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Schumaker, Anna" X-Patchwork-Id: 12747547 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 66ADEC433EF for ; Tue, 15 Feb 2022 19:22:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239959AbiBOTWK (ORCPT ); Tue, 15 Feb 2022 14:22:10 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:56800 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239247AbiBOTWJ (ORCPT ); Tue, 15 Feb 2022 14:22:09 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C395E75E7C for ; Tue, 15 Feb 2022 11:21:57 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 5E351617C3 for ; Tue, 15 Feb 2022 19:21:57 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7AEFCC340F2; Tue, 15 Feb 2022 19:21:56 +0000 (UTC) From: Anna.Schumaker@Netapp.com To: steved@redhat.com, linux-nfs@vger.kernel.org Cc: Anna.Schumaker@Netapp.com Subject: [PATCH v8 9/9] rpcctl: Add installation to the Makefile Date: Tue, 15 Feb 2022 14:21:50 -0500 Message-Id: <20220215192150.53811-10-Anna.Schumaker@Netapp.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220215192150.53811-1-Anna.Schumaker@Netapp.com> References: <20220215192150.53811-1-Anna.Schumaker@Netapp.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org From: Anna Schumaker And create a shell script that launches the python program from the $(libdir) Signed-off-by: Anna Schumaker --- configure.ac | 1 + tools/Makefile.am | 2 +- tools/rpcctl/Makefile.am | 13 +++++++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 tools/rpcctl/Makefile.am diff --git a/configure.ac b/configure.ac index 50e9b321dcf3..e0f5a9301956 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..33fb431fe7d4 --- /dev/null +++ b/tools/rpcctl/Makefile.am @@ -0,0 +1,13 @@ +## Process this file with automake to produce Makefile.in +PYTHON_FILES = rpcctl.py + +man8_MANS = rpcctl.man + +EXTRA_DIST = $(man8_MANS) $(PYTHON_FILES) + +all-local: $(PYTHON_FILES) + +install-data-hook: + $(INSTALL) -m 755 rpcctl.py $(DESTDIR)$(sbindir)/rpcctl + +MAINTAINERCLEANFILES=Makefile.in