Message ID | 00eab2a417ecdb7f0ea7eaf3880806f3309133dc.1742315602.git.pkrempa@redhat.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | scripts: render_block_graph: Fix with new python and improve argument parsing | expand |
On Tue, Mar 18, 2025 at 05:36:03PM +0100, Peter Krempa wrote: > From: Peter Krempa <pkrempa@redhat.com> > > As no argument parsing is employed the script is hard to use and when > running without arguments it blurbs: > > $ ./scripts/render_block_graph.py > Traceback (most recent call last): > File "/home/pipo/git/qemu.git/./scripts/render_block_graph.py", line 135, in <module> > obj = sys.argv[1] > ~~~~~~~~^^^ > IndexError: list index out of range > > instead of an actionable error. The user then usually needs to read the > script to understand arguments. > > Implement proper argument parsing via 'argparse'. The following > arguments will be supported: > > $ ./scripts/render_block_graph.py --help > usage: render_block_graph.py [-h] [--socket SOCKET] [--vm VM] [--uri URI] [--output OUTPUT] > > Tool that renders the qemu block graph into a image. > > options: > -h, --help show this help message and exit > --socket SOCKET direct mode - path to qemu monitor socket > --vm VM libvirt mode - name of libvirt VM > --uri URI libvirt URI to connect to > --output OUTPUT path to output image; .png suffix will be added; in libvirt mode default is the name of the VM > > Usage then requires one of '--vm' or '--socket'. In libvirt mode the > output file is by default populated from the VM name and the '--uri' > parameter allows overriding the libvirt connection uri. > > Signed-off-by: Peter Krempa <pkrempa@redhat.com> > --- > scripts/render_block_graph.py | 53 ++++++++++++++++++++++++++++------- > 1 file changed, 43 insertions(+), 10 deletions(-) > > diff --git a/scripts/render_block_graph.py b/scripts/render_block_graph.py > index 14b2d02ec2..7a6738410c 100755 > --- a/scripts/render_block_graph.py > +++ b/scripts/render_block_graph.py > @@ -23,6 +23,7 @@ > import subprocess > import json > from graphviz import Digraph > +import argparse > > sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'python')) > from qemu.qmp import QMPError > @@ -91,13 +92,19 @@ def render_block_graph(qmp, filename, format='png'): > > > class LibvirtGuest(): > - def __init__(self, name): > + def __init__(self, name, uri=None): > self.name = name > + self.uri = uri > > def cmd(self, cmd): > # only supports qmp commands without parameters > m = {'execute': cmd} > - ar = ['virsh', 'qemu-monitor-command', self.name, json.dumps(m)] > + ar = ['virsh'] > + > + if self.uri: > + ar += ['-c', self.uri] > + > + ar += ['qemu-monitor-command', self.name, json.dumps(m)] > > reply = json.loads(subprocess.check_output(ar)) > > @@ -108,15 +115,41 @@ def cmd(self, cmd): > > > if __name__ == '__main__': > - obj = sys.argv[1] > - out = sys.argv[2] > + parser = argparse.ArgumentParser( > + description='Tool that renders the qemu block graph into a image.') > + > + parser.add_argument('--socket', > + help='direct mode - path to qemu monitor socket') > + > + parser.add_argument('--vm', help='libvirt mode - name of libvirt VM') > + parser.add_argument('--uri', help='libvirt URI to connect to') > + > + parser.add_argument('--output', > + help='path to output image (.png suffix added);' > + 'in libvirt mode default is the name of the VM') > + > + args = parser.parse_args() > > - if os.path.exists(obj): > - # assume unix socket > - qmp = QEMUMonitorProtocol(obj) > + if (args.socket and args.vm) or (not args.socket and not args.vm): > + print("One of --socket or --vm is required.", file=sys.stderr) > + parser.print_help() > + sys.exit(1) It's possible to do with argparse as well: modegroup = parser.add_mutually_exclusive_group(required=True) modegroup.add_argument('--socket', help='direct mode - path to qemu monitor socket') modegroup.add_argument('--vm', help='libvirt mode - name of libvirt VM') The only difference is that it will print usage `parser.print_usage()`. > + > + if args.socket: > + qmp = QEMUMonitorProtocol(args.socket) > qmp.connect() > - else: > - # assume libvirt guest name > - qmp = LibvirtGuest(obj) > + > + if args.vm: > + qmp = LibvirtGuest(args.vm, args.uri) > + > + if args.output: > + out = args.output > + else: > + out = args.vm > + > + if not out: This needs to use args.output otherwise python will complain that it doesn't know `out` variable. > + print("--output required", file=sys.stderr) > + parser.print_help() Probably use `parser.print_usage()` if you decide to use the add_mutually_exclusive_group(). Pavel > + sys.exit(1) > > render_block_graph(qmp, out) > -- > 2.48.1 > >
diff --git a/scripts/render_block_graph.py b/scripts/render_block_graph.py index 14b2d02ec2..7a6738410c 100755 --- a/scripts/render_block_graph.py +++ b/scripts/render_block_graph.py @@ -23,6 +23,7 @@ import subprocess import json from graphviz import Digraph +import argparse sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'python')) from qemu.qmp import QMPError @@ -91,13 +92,19 @@ def render_block_graph(qmp, filename, format='png'): class LibvirtGuest(): - def __init__(self, name): + def __init__(self, name, uri=None): self.name = name + self.uri = uri def cmd(self, cmd): # only supports qmp commands without parameters m = {'execute': cmd} - ar = ['virsh', 'qemu-monitor-command', self.name, json.dumps(m)] + ar = ['virsh'] + + if self.uri: + ar += ['-c', self.uri] + + ar += ['qemu-monitor-command', self.name, json.dumps(m)] reply = json.loads(subprocess.check_output(ar)) @@ -108,15 +115,41 @@ def cmd(self, cmd): if __name__ == '__main__': - obj = sys.argv[1] - out = sys.argv[2] + parser = argparse.ArgumentParser( + description='Tool that renders the qemu block graph into a image.') + + parser.add_argument('--socket', + help='direct mode - path to qemu monitor socket') + + parser.add_argument('--vm', help='libvirt mode - name of libvirt VM') + parser.add_argument('--uri', help='libvirt URI to connect to') + + parser.add_argument('--output', + help='path to output image (.png suffix added);' + 'in libvirt mode default is the name of the VM') + + args = parser.parse_args() - if os.path.exists(obj): - # assume unix socket - qmp = QEMUMonitorProtocol(obj) + if (args.socket and args.vm) or (not args.socket and not args.vm): + print("One of --socket or --vm is required.", file=sys.stderr) + parser.print_help() + sys.exit(1) + + if args.socket: + qmp = QEMUMonitorProtocol(args.socket) qmp.connect() - else: - # assume libvirt guest name - qmp = LibvirtGuest(obj) + + if args.vm: + qmp = LibvirtGuest(args.vm, args.uri) + + if args.output: + out = args.output + else: + out = args.vm + + if not out: + print("--output required", file=sys.stderr) + parser.print_help() + sys.exit(1) render_block_graph(qmp, out)