#!/usr/bin/env python3 # # (c) 2019-2022 Antmicro # License: Apache-2.0 # import argparse import sys import time from common import * # Declare and parse command line flags parser = argparse.ArgumentParser() parser.add_argument('session', metavar='SESSION-NAME', type=str, nargs='?', default=None, help='sargraph session name') parser.add_argument('command', metavar='COMMAND', type=str, nargs='*', help='send command') parser.add_argument('-f', metavar='DEVICE-NAME', type=str, nargs='?', default=None, dest='fsdev', help='observe a chosen filesystem') parser.add_argument('-m', metavar='MOUNT-DIR', type=str, nargs='?', default=None, dest='fspath', help='observe a chosen filesystem') parser.add_argument('-o', metavar='OUTPUT-NAME', type=str, nargs='?', default='data', dest='name', help='set output base names') args = parser.parse_args() def send(sid, msg): p = subprocess.Popen(["screen", "-S", sid, "-X", "stuff", f"{msg}\n"]) while p.poll() is None: time.sleep(0.1) # Check if sar is available p = run_or_fail("sar", "-V", stdout=subprocess.PIPE) # Check if screen is available p = run_or_fail("screen", "-v", stdout=subprocess.PIPE) version = scan("Screen version (\d+)", int, p.stdout.readline().decode()) if version is None: fail("'screen' tool returned unknown output") # If the script was run with no parameters, run in background and gather data if args.session is None: import watch # Find requested disk device if args.fspath: args.fspath = os.path.realpath(args.fspath) with open("/proc/self/mounts", "r") as f: while args.fsdev is None: args.fsdev = scan(f"^(/dev/\S+)\s+{re.escape(args.fspath)}\s+", str, f.readline()) if not args.fsdev: fail(f"no device is mounted on {args.fspath}") watch.watch(args.name, args.fsdev) sys.exit(0) # Now handle the commands # Check if a command was provided if len(args.command) <= 0: fail("command not provided") # Get session name and command name sid = args.session cmd = args.command if cmd[0] == "start": print(f"Starting sargraph session '{sid}'") # Spawn watcher process, *sys.argv[3:] is all arguments after 'chart start' p = subprocess.Popen(["screen", "-Logfile", f"{sid}.log", "-dmSL", sid, os.path.realpath(__file__), *sys.argv[3:], '-o', sid]) while p.poll() is None: time.sleep(0.1) gpid = 0 j = 0 time.sleep(1) print(f"Session '{sid}' started") elif cmd[0] == "stop": print(f"Terminating sargraph session '{sid}'") try: gpid = int(os.popen(f"screen -ls | grep '.{sid}' | tr -d ' \t' | cut -f 1 -d '.'").read()) except: print("Warning: cannot find pid.") gpid = -1 if len(cmd) < 2: send(sid, "command:q:") else: send(sid, f"command:q:{cmd[1]}") if gpid == -1: print("Waiting 3 seconds.") time.sleep(3) else: while pid_running(gpid): time.sleep(0.25) elif cmd[0] == "label": # Check if the label name was provided if len(cmd) < 2: fail("label command requires an additional parameter") print(f"Adding label '{cmd[1]}' to sargraph session '{sid}'.") send(sid, f"label:{cmd[1]}") elif cmd[0] == 'save': print(f"Saving graph from session '{sid}'.") if len(cmd) < 2: send(sid, "command:s:") else: send(sid, f"command:s:{cmd[1]}") elif cmd[0] == 'plot': import graph if len(cmd) < 2: graph.graph(sid) else: graph.graph(sid, cmd[1]) else: fail(f"unknown command '{cmd[0]}'")