DPDK patches and discussions
 help / color / mirror / Atom feed
From: Stephen Hemminger <stephen@networkplumber.org>
To: dev@dpdk.org
Cc: Stephen Hemminger <stephen@networkplumber.org>
Subject: [dpdk-dev] [PATCH 11/11] dpdk-devbind: use argparse instead of getopt
Date: Sat,  5 Sep 2020 18:31:33 -0700
Message-ID: <20200906013133.26360-12-stephen@networkplumber.org> (raw)
In-Reply-To: <20200906013133.26360-1-stephen@networkplumber.org>

Using the python standard argument parser instead of C library
style getopt gives a number of advantages such as checking
for conflicting arguments, restricting choices, and automatically
generating help messages.

The result is similar to the original the only visible change
is that some of the help messages are now less wordy.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 usertools/dpdk-devbind.py | 196 +++++++++++++++++---------------------
 1 file changed, 85 insertions(+), 111 deletions(-)

diff --git a/usertools/dpdk-devbind.py b/usertools/dpdk-devbind.py
index bcdc5da881d9..33d3ef798f7d 100755
--- a/usertools/dpdk-devbind.py
+++ b/usertools/dpdk-devbind.py
@@ -5,8 +5,8 @@
 
 import sys
 import os
-import getopt
 import subprocess
+import argparse
 from os.path import exists, abspath, dirname, basename
 
 # The PCI base class for all devices
@@ -72,76 +72,6 @@
 args = []
 
 
-def usage():
-    '''Print usage information for the program'''
-    argv0 = basename(sys.argv[0])
-    print("""
-Usage:
-------
-
-     %(argv0)s [options] DEVICE1 DEVICE2 ....
-
-where DEVICE1, DEVICE2 etc, are specified via PCI "domain:bus:slot.func" syntax
-or "bus:slot.func" syntax. For devices bound to Linux kernel drivers, they may
-also be referred to by Linux interface name e.g. eth0, eth1, em0, em1, etc.
-
-Options:
-    --help, --usage:
-        Display usage information and quit
-
-    -s, --status:
-        Print the current status of all known network, crypto, event
-        and mempool devices.
-        For each device, it displays the PCI domain, bus, slot and function,
-        along with a text description of the device. Depending upon whether the
-        device is being used by a kernel driver, the igb_uio driver, or no
-        driver, other relevant information will be displayed:
-        * the Linux interface name e.g. if=eth0
-        * the driver being used e.g. drv=igb_uio
-        * any suitable drivers not currently using that device
-            e.g. unused=igb_uio
-        NOTE: if this flag is passed along with a bind/unbind option, the
-        status display will always occur after the other operations have taken
-        place.
-
-    --status-dev:
-        Print the status of given device group. Supported device groups are:
-        "net", "baseband", "crypto", "event", "mempool" and "compress"
-
-    -b driver, --bind=driver:
-        Select the driver to use or \"none\" to unbind the device
-
-    -u, --unbind:
-        Unbind a device (Equivalent to \"-b none\")
-
-    --force:
-        By default, network devices which are used by Linux - as indicated by
-        having routes in the routing table - cannot be modified. Using the
-        --force flag overrides this behavior, allowing active links to be
-        forcibly unbound.
-        WARNING: This can lead to loss of network connection and should be used
-        with caution.
-
-Examples:
----------
-
-To display current device status:
-        %(argv0)s --status
-
-To display current network device status:
-        %(argv0)s --status-dev net
-
-To bind eth1 from the current driver and move to use igb_uio
-        %(argv0)s --bind=igb_uio eth1
-
-To unbind 0000:01:00.0 from using any driver
-        %(argv0)s -u 0000:01:00.0
-
-To bind 0000:02:00.0 and 0000:02:00.1 to the ixgbe kernel driver
-        %(argv0)s -b ixgbe 02:00.0 02:00.1
-
-    """ % locals())  # replace items from local variables
-
 # check if a specific kernel module is loaded
 def module_is_loaded(module):
     global loaded_modules
@@ -642,38 +572,93 @@ def parse_args():
     global status_dev
     global force_flag
     global args
-    if len(sys.argv) <= 1:
-        usage()
-        sys.exit(0)
 
-    try:
-        opts, args = getopt.getopt(sys.argv[1:], "b:us",
-                                   ["help", "usage", "status", "status-dev=",
-                                    "force", "bind=", "unbind", ])
-    except getopt.GetoptError as error:
-        print(str(error))
-        print("Run '%s --usage' for further information" % sys.argv[0])
+    parser = argparse.ArgumentParser(
+        description='Utility to bind and unbind devices from Linux kernel',
+        formatter_class=argparse.RawDescriptionHelpFormatter,
+        epilog="""
+Examples:
+---------
+
+To display current device status:
+        %(prog)s --status
+
+To display current network device status:
+        %(prog)s --status-dev net
+
+To bind eth1 from the current driver and move to use vfio-pci
+        %(prog)s --bind=vfio-pci eth1
+
+To unbind 0000:01:00.0 from using any driver
+        %(prog)s -u 0000:01:00.0
+
+To bind 0000:02:00.0 and 0000:02:00.1 to the ixgbe kernel driver
+        %(prog)s -b ixgbe 02:00.0 02:00.1
+""")
+
+    parser.add_argument(
+        '-s',
+        '--status',
+        action='store_true',
+        help="Print the current status of all known devices.")
+    parser.add_argument(
+        '--status-dev',
+        help="Print the status of given device group.",
+        choices=['net', 'baseband', 'crypto', 'event', 'mempool', 'compress'])
+    bind_group = parser.add_mutually_exclusive_group()
+    bind_group.add_argument(
+        '-b',
+        '--bind',
+        metavar='DRIVER',
+        help="Select the driver to use or \"none\" to unbind the device")
+    bind_group.add_argument(
+        '-u',
+        '--unbind',
+        action='store_true',
+        help="Unbind a device (equivalent to \"-b none\")")
+    parser.add_argument(
+        '--force',
+        action='store_true',
+        help="""
+Override restriction on binding devices in use by Linux"
+WARNING: This can lead to loss of network connection and should be used with caution.
+""")
+    parser.add_argument(
+        'devices',
+        metavar='DEVICE',
+        nargs='*',
+        help="""
+Device specified as PCI "domain:bus:slot.func" syntax or "bus:slot.func" syntax.
+For devices bound to Linux kernel drivers, they may be referred to by interface name.
+""")
+
+    opt = parser.parse_args()
+
+    if opt.status_dev:
+        status_flag = True
+        status_dev = opt.status_dev
+    if opt.status:
+        status_flag = True
+        status_dev = "all"
+    if opt.force:
+        force_flag = True
+    if opt.bind:
+        b_flag = opt.bind
+    elif opt.unbind:
+        b_flag = "none"
+    args = opt.devices
+
+    if not b_flag and not status_flag:
+        print("Error: No action specified for devices. "
+              "Please give a --bind, --ubind or --status option",
+              file=sys.stderr)
+        parser.print_usage()
         sys.exit(1)
 
-    for opt, arg in opts:
-        if opt == "--help" or opt == "--usage":
-            usage()
-            sys.exit(0)
-        if opt == "--status-dev":
-            status_flag = True
-            status_dev = arg
-        if opt == "--status" or opt == "-s":
-            status_flag = True
-            status_dev = "all"
-        if opt == "--force":
-            force_flag = True
-        if opt == "-b" or opt == "-u" or opt == "--bind" or opt == "--unbind":
-            if b_flag is not None:
-                sys.exit("Error: binding and unbinding are mutually exclusive")
-            if opt == "-u" or opt == "--unbind":
-                b_flag = "none"
-            else:
-                b_flag = arg
+    if b_flag and not args:
+        print("Error: No devices specified.", file=sys.stderr)
+        parser.print_usage()
+        sys.exit(1)
 
 
 def do_arg_actions():
@@ -683,17 +668,6 @@ def do_arg_actions():
     global force_flag
     global args
 
-    if b_flag is None and not status_flag:
-        print("Error: No action specified for devices. "
-              "Please give a -b or -u option", file=sys.stderr)
-        usage()
-        sys.exit(1)
-
-    if b_flag is not None and len(args) == 0:
-        print("Error: No devices specified.", file=sys.stderr)
-        usage()
-        sys.exit(1)
-
     if b_flag == "none" or b_flag == "None":
         unbind_all(args, force_flag)
     elif b_flag is not None:
-- 
2.27.0


  parent reply	other threads:[~2020-09-06  1:33 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-09-06  1:31 [dpdk-dev] [PATCH 00/11] Python script updates Stephen Hemminger
2020-09-06  1:31 ` [dpdk-dev] [PATCH 01/11] cpu_layout: refactor to meet python standards Stephen Hemminger
2020-11-04  6:53   ` [dpdk-dev] [PATCH v2] " Stephen Hemminger
2020-11-04  9:21     ` Bruce Richardson
2020-11-04 16:22       ` Stephen Hemminger
2020-09-06  1:31 ` [dpdk-dev] [PATCH 02/11] dpdk-pmdinfo: replace string.split with split Stephen Hemminger
2020-11-04  6:48   ` [dpdk-dev] [PATCH v2 0/7] dpdk-pmdinfo: python lint cleanups Stephen Hemminger
2020-11-04  6:48     ` [dpdk-dev] [PATCH v2 1/7] dpdk-pmdinfo: replace string.split with split Stephen Hemminger
2020-11-04  6:48     ` [dpdk-dev] [PATCH v2 2/7] dpdk-pmdinfo: replace io.open with open Stephen Hemminger
2020-11-04  6:48     ` [dpdk-dev] [PATCH v2 3/7] dpdk-pmdinfo: remove unnecessary paren and else Stephen Hemminger
2020-11-04  6:48     ` [dpdk-dev] [PATCH v2 4/7] dpdk-pmdinfo: replace is False and is True Stephen Hemminger
2020-11-04  6:48     ` [dpdk-dev] [PATCH v2 5/7] dpdk-pmdinfo: fix indentation Stephen Hemminger
2020-11-04  6:48     ` [dpdk-dev] [PATCH v2 6/7] dpdk-pmdinfo: replace deprecated optparse with argparse Stephen Hemminger
2020-11-24  6:35       ` Jiang, YuX
2020-11-04  6:48     ` [dpdk-dev] [PATCH v2 7/7] dpdk-pmdinfo: do not use len(x) to test for empty Stephen Hemminger
2020-11-22 20:54     ` [dpdk-dev] [PATCH v2 0/7] dpdk-pmdinfo: python lint cleanups Thomas Monjalon
2020-09-06  1:31 ` [dpdk-dev] [PATCH 03/11] dpdk-pmdinfo: replace io.open with open Stephen Hemminger
2020-09-06  1:31 ` [dpdk-dev] [PATCH 04/11] dpdk-pmdinfo: remove dead code Stephen Hemminger
2020-09-06  1:31 ` [dpdk-dev] [PATCH 05/11] dpdk-pmdinfo: remove unnecessary paren and else Stephen Hemminger
2020-09-06  1:31 ` [dpdk-dev] [PATCH 06/11] dpdk-pmdinfo: replace is False and is True Stephen Hemminger
2020-09-06  1:31 ` [dpdk-dev] [PATCH 07/11] dpdk-pmdinfo: fix indentation Stephen Hemminger
2020-09-06  1:31 ` [dpdk-dev] [PATCH 08/11] dpdk-pmdinfo: replace deprecated optparse with argparse Stephen Hemminger
2020-09-06  1:31 ` [dpdk-dev] [PATCH 09/11] dpdk-pmdinfo: do not use len(x) to test for empty Stephen Hemminger
2020-09-07  9:03   ` Bruce Richardson
2020-09-07 17:20     ` Stephen Hemminger
2020-09-06  1:31 ` [dpdk-dev] [PATCH 10/11] dpdk-telemetry-client: fix some pylint warnings Stephen Hemminger
2020-09-07  9:05   ` Bruce Richardson
2020-11-04  7:00   ` [dpdk-dev] [PATCH v2] " Stephen Hemminger
2020-11-15 23:06     ` Thomas Monjalon
2020-09-06  1:31 ` Stephen Hemminger [this message]
2020-11-04  7:03   ` [dpdk-dev] [PATCH v2 0/6] dpdk-devbind: python lint cleanups Stephen Hemminger
2020-11-04  7:03     ` [dpdk-dev] [PATCH v2 1/6] dpdk-devbind: use argparse instead of getopt Stephen Hemminger
2020-11-04  7:03     ` [dpdk-dev] [PATCH v2 2/6] dpdk-devbind: fix indentation Stephen Hemminger
2020-11-04  7:03     ` [dpdk-dev] [PATCH v2 3/6] dpdk-devbind: fix python lint warnings for imports Stephen Hemminger
2020-11-04  7:03     ` [dpdk-dev] [PATCH v2 4/6] dpdk-devbind: do not use len(x) to test for empty Stephen Hemminger
2020-11-04  7:03     ` [dpdk-dev] [PATCH v2 5/6] dpdk-devbind: fix unnecessary else after return Stephen Hemminger
2020-11-04  7:03     ` [dpdk-dev] [PATCH v2 6/6] dpdk-devbind: use in to test for multiple strings Stephen Hemminger
2020-11-04  9:28     ` [dpdk-dev] [PATCH v2 0/6] dpdk-devbind: python lint cleanups Bruce Richardson
2020-11-22 21:03       ` Thomas Monjalon
2020-11-04 16:57     ` Stephen Hemminger

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=20200906013133.26360-12-stephen@networkplumber.org \
    --to=stephen@networkplumber.org \
    --cc=dev@dpdk.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

DPDK patches and discussions

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://inbox.dpdk.org/dev/0 dev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 dev dev/ https://inbox.dpdk.org/dev \
		dev@dpdk.org
	public-inbox-index dev

Example config snippet for mirrors.
Newsgroup available over NNTP:
	nntp://inbox.dpdk.org/inbox.dpdk.dev


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git