1#! /usr/bin/env python3 2# SPDX-License-Identifier: BSD-3-Clause 3# Copyright(c) 2020 Intel Corporation 4 5""" 6Script to be used with V2 Telemetry. 7Allows the user input commands and read the Telemetry response. 8""" 9 10import socket 11import os 12import glob 13import json 14import errno 15import readline 16import argparse 17 18# global vars 19TELEMETRY_VERSION = "v2" 20CMDS = [] 21 22 23def read_socket(sock, buf_len, echo=True): 24 """ Read data from socket and return it in JSON format """ 25 reply = sock.recv(buf_len).decode() 26 try: 27 ret = json.loads(reply) 28 except json.JSONDecodeError: 29 print("Error in reply: ", reply) 30 sock.close() 31 raise 32 if echo: 33 print(json.dumps(ret)) 34 return ret 35 36 37def get_app_name(pid): 38 """ return the app name for a given PID, for printing """ 39 proc_cmdline = os.path.join('/proc', str(pid), 'cmdline') 40 try: 41 with open(proc_cmdline) as f: 42 argv0 = f.read(1024).split('\0')[0] 43 return os.path.basename(argv0) 44 except IOError as e: 45 # ignore file not found errors 46 if e.errno != errno.ENOENT: 47 raise 48 return None 49 50 51def handle_socket(path): 52 """ Connect to socket and handle user input """ 53 sock = socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET) 54 global CMDS 55 print("Connecting to " + path) 56 try: 57 sock.connect(path) 58 except OSError: 59 print("Error connecting to " + path) 60 sock.close() 61 return 62 json_reply = read_socket(sock, 1024) 63 output_buf_len = json_reply["max_output_len"] 64 app_name = get_app_name(json_reply["pid"]) 65 if app_name: 66 print('Connected to application: "%s"' % app_name) 67 68 # get list of commands for readline completion 69 sock.send("/".encode()) 70 CMDS = read_socket(sock, output_buf_len, False)["/"] 71 72 # interactive prompt 73 text = input('--> ').strip() 74 while text != "quit": 75 if text.startswith('/'): 76 sock.send(text.encode()) 77 read_socket(sock, output_buf_len) 78 text = input('--> ').strip() 79 sock.close() 80 81 82def readline_complete(text, state): 83 """ Find any matching commands from the list based on user input """ 84 all_cmds = ['quit'] + CMDS 85 if text: 86 matches = [c for c in all_cmds if c.startswith(text)] 87 else: 88 matches = all_cmds 89 return matches[state] 90 91 92def get_dpdk_runtime_dir(fp): 93 """ Using the same logic as in DPDK's EAL, get the DPDK runtime directory 94 based on the file-prefix and user """ 95 if (os.getuid() == 0): 96 return os.path.join('/var/run/dpdk', fp) 97 return os.path.join(os.environ.get('XDG_RUNTIME_DIR', '/tmp'), 'dpdk', fp) 98 99 100readline.parse_and_bind('tab: complete') 101readline.set_completer(readline_complete) 102readline.set_completer_delims(readline.get_completer_delims().replace('/', '')) 103 104parser = argparse.ArgumentParser() 105parser.add_argument('-f', '--file-prefix', \ 106 help='Provide file-prefix for DPDK runtime directory', default='rte') 107args = parser.parse_args() 108rdir = get_dpdk_runtime_dir(args.file_prefix) 109handle_socket(os.path.join(rdir, 'dpdk_telemetry.{}'.format(TELEMETRY_VERSION))) 110