129784f35SKrzysztof Karas#!/usr/bin/env python3 229784f35SKrzysztof Karas# SPDX-License-Identifier: BSD-3-Clause 329784f35SKrzysztof Karas# Copyright (C) 2019 Intel Corporation 429784f35SKrzysztof Karas# All rights reserved. 529784f35SKrzysztof Karas# 629784f35SKrzysztof Karas 729784f35SKrzysztof Karasimport logging 829784f35SKrzysztof Karasimport argparse 929784f35SKrzysztof Karasimport sys 1029784f35SKrzysztof Karasimport shlex 1129784f35SKrzysztof Karas 1229784f35SKrzysztof Karastry: 1329784f35SKrzysztof Karas from spdk.rpc.client import print_dict, JSONRPCException 1429784f35SKrzysztof Karas import spdk.rpc as rpc 1529784f35SKrzysztof Karasexcept ImportError: 1629784f35SKrzysztof Karas print("SPDK RPC library missing. Please add spdk/python directory to PYTHONPATH:") 1729784f35SKrzysztof Karas print("'export PYTHONPATH=$PYTHONPATH:spdk/python'") 1829784f35SKrzysztof Karas exit(1) 1929784f35SKrzysztof Karas 2029784f35SKrzysztof Karastry: 2129784f35SKrzysztof Karas from shlex import quote 2229784f35SKrzysztof Karasexcept ImportError: 2329784f35SKrzysztof Karas from pipes import quote 2429784f35SKrzysztof Karas 25bbf8dfb7SEugene KobyakPATTERN_TYPES_STR = ("read", "write", "randread", "randwrite", "rw", "randrw", "verify", "reset", 26bbf8dfb7SEugene Kobyak "unmap", "flush", "write_zeroes") 27bbf8dfb7SEugene Kobyak 2829784f35SKrzysztof Karas 2929784f35SKrzysztof Karasdef print_array(a): 3029784f35SKrzysztof Karas print(" ".join((quote(v) for v in a))) 3129784f35SKrzysztof Karas 3229784f35SKrzysztof Karas 33bbf8dfb7SEugene Kobyakdef perform_tests_func(args): 34bbf8dfb7SEugene Kobyak """Perform bdevperf tests with command line arguments. 3529784f35SKrzysztof Karas 3629784f35SKrzysztof Karas Args: 3729784f35SKrzysztof Karas none 3829784f35SKrzysztof Karas 3929784f35SKrzysztof Karas Returns: 4029784f35SKrzysztof Karas On success, 0 is returned. On error, -1 is returned. 4129784f35SKrzysztof Karas """ 42bbf8dfb7SEugene Kobyak client = args.client 43bbf8dfb7SEugene Kobyak param_names = ['queue_depth', 'time_in_sec', 'workload_type', 'io_size', 'rw_percentage'] 44bbf8dfb7SEugene Kobyak params = {name: getattr(args, name) for name in param_names if getattr(args, name, None)} 4529784f35SKrzysztof Karas return client.call('perform_tests', params) 4629784f35SKrzysztof Karas 4729784f35SKrzysztof Karas 4829784f35SKrzysztof Karasif __name__ == "__main__": 4929784f35SKrzysztof Karas parser = argparse.ArgumentParser( 5029784f35SKrzysztof Karas description='SPDK RPC command line interface. NOTE: spdk/python is expected in PYTHONPATH') 5129784f35SKrzysztof Karas parser.add_argument('-s', dest='server_addr', 5229784f35SKrzysztof Karas help='RPC domain socket path or IP address', default='/var/tmp/spdk.sock') 5329784f35SKrzysztof Karas parser.add_argument('-p', dest='port', 5429784f35SKrzysztof Karas help='RPC port number (if server_addr is IP address)', 5529784f35SKrzysztof Karas default=5260, type=int) 5629784f35SKrzysztof Karas parser.add_argument('-t', dest='timeout', 5729784f35SKrzysztof Karas help='Timeout as a floating point number expressed in seconds waiting for response. Default: 60.0', 5829784f35SKrzysztof Karas default=60.0, type=float) 5929784f35SKrzysztof Karas parser.add_argument('-v', dest='verbose', action='store_const', const="INFO", 6029784f35SKrzysztof Karas help='Set verbose mode to INFO', default="ERROR") 6129784f35SKrzysztof Karas parser.add_argument('--verbose', dest='verbose', choices=['DEBUG', 'INFO', 'ERROR'], 6229784f35SKrzysztof Karas help="""Set verbose level. """) 6329784f35SKrzysztof Karas subparsers = parser.add_subparsers(help='RPC methods') 6429784f35SKrzysztof Karas 6529784f35SKrzysztof Karas def perform_tests(args): 66bbf8dfb7SEugene Kobyak print_dict(perform_tests_func(args)) 6729784f35SKrzysztof Karas 68bbf8dfb7SEugene Kobyak perform_tests_help_string = ''' 69bbf8dfb7SEugene Kobyak Perform bdevperf tests 70bbf8dfb7SEugene Kobyak All parameters are optional. 71bbf8dfb7SEugene Kobyak If any parameter provided it will overwrite ones from prior run or command line. 72bbf8dfb7SEugene Kobyak If job config file was used no parameter should be provided. 73bbf8dfb7SEugene Kobyak ''' 74bbf8dfb7SEugene Kobyak p = subparsers.add_parser('perform_tests', help=perform_tests_help_string) 75bbf8dfb7SEugene Kobyak p.add_argument('-q', dest="queue_depth", help='io depth', type=int) 76bbf8dfb7SEugene Kobyak p.add_argument('-o', dest="io_size", help='Size in bytes', type=str) 77bbf8dfb7SEugene Kobyak p.add_argument('-t', dest="time_in_sec", help='Time in seconds', type=int) 78bbf8dfb7SEugene Kobyak p.add_argument('-M', dest="rw_percentage", help='rwmixread (100 for reads, 0 for writes)', 79bbf8dfb7SEugene Kobyak type=int, choices=range(0, 101), metavar="[0-100]") 80bbf8dfb7SEugene Kobyak p.add_argument('-w', dest="workload_type", choices=PATTERN_TYPES_STR, type=str.lower, 81bbf8dfb7SEugene Kobyak help=f'io pattern type, must be one of {PATTERN_TYPES_STR}',) 8229784f35SKrzysztof Karas p.set_defaults(func=perform_tests) 8329784f35SKrzysztof Karas 8429784f35SKrzysztof Karas def call_rpc_func(args): 8529784f35SKrzysztof Karas try: 8629784f35SKrzysztof Karas args.func(args) 8729784f35SKrzysztof Karas except JSONRPCException as ex: 8829784f35SKrzysztof Karas print(ex.message) 8929784f35SKrzysztof Karas exit(1) 9029784f35SKrzysztof Karas 9129784f35SKrzysztof Karas def execute_script(parser, client, fd): 9229784f35SKrzysztof Karas for rpc_call in map(str.rstrip, fd): 9329784f35SKrzysztof Karas if not rpc_call.strip(): 9429784f35SKrzysztof Karas continue 9529784f35SKrzysztof Karas args = parser.parse_args(shlex.split(rpc_call)) 9629784f35SKrzysztof Karas args.client = client 9729784f35SKrzysztof Karas call_rpc_func(args) 9829784f35SKrzysztof Karas 9929784f35SKrzysztof Karas args = parser.parse_args() 100*db026688SMarcin Spiewak if args.time_in_sec is not None: 101*db026688SMarcin Spiewak args.timeout = max(float(args.time_in_sec + 5), args.timeout) 10229784f35SKrzysztof Karas args.client = rpc.client.JSONRPCClient(args.server_addr, args.port, args.timeout, log_level=getattr(logging, args.verbose.upper())) 10329784f35SKrzysztof Karas if hasattr(args, 'func'): 10429784f35SKrzysztof Karas call_rpc_func(args) 10529784f35SKrzysztof Karas elif sys.stdin.isatty(): 10629784f35SKrzysztof Karas # No arguments and no data piped through stdin 10729784f35SKrzysztof Karas parser.print_help() 10829784f35SKrzysztof Karas exit(1) 10929784f35SKrzysztof Karas else: 11029784f35SKrzysztof Karas execute_script(parser, args.client, sys.stdin) 111