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 9*552eaa9cSKonrad Sztyberimport os 1029784f35SKrzysztof Karasimport sys 1129784f35SKrzysztof Karasimport shlex 1229784f35SKrzysztof Karas 1329784f35SKrzysztof Karastry: 1429784f35SKrzysztof Karas from shlex import quote 1529784f35SKrzysztof Karasexcept ImportError: 1629784f35SKrzysztof Karas from pipes import quote 1729784f35SKrzysztof Karas 18*552eaa9cSKonrad Sztybertry: 19*552eaa9cSKonrad Sztyber sys.path.append(os.path.dirname(__file__) + '/../../../python') 20*552eaa9cSKonrad Sztyber from spdk.rpc.client import print_dict, JSONRPCException # noqa 21*552eaa9cSKonrad Sztyber import spdk.rpc as rpc # noqa 22*552eaa9cSKonrad Sztyberexcept ImportError: 23*552eaa9cSKonrad Sztyber print("SPDK RPC library missing. Please add spdk/python directory to PYTHONPATH:") 24*552eaa9cSKonrad Sztyber print("'export PYTHONPATH=$PYTHONPATH:spdk/python'") 25*552eaa9cSKonrad Sztyber exit(1) 26*552eaa9cSKonrad Sztyber 27*552eaa9cSKonrad Sztyber 28bbf8dfb7SEugene KobyakPATTERN_TYPES_STR = ("read", "write", "randread", "randwrite", "rw", "randrw", "verify", "reset", 29bbf8dfb7SEugene Kobyak "unmap", "flush", "write_zeroes") 30bbf8dfb7SEugene Kobyak 3129784f35SKrzysztof Karas 3229784f35SKrzysztof Karasdef print_array(a): 3329784f35SKrzysztof Karas print(" ".join((quote(v) for v in a))) 3429784f35SKrzysztof Karas 3529784f35SKrzysztof Karas 36bbf8dfb7SEugene Kobyakdef perform_tests_func(args): 37bbf8dfb7SEugene Kobyak """Perform bdevperf tests with command line arguments. 3829784f35SKrzysztof Karas 3929784f35SKrzysztof Karas Args: 4029784f35SKrzysztof Karas none 4129784f35SKrzysztof Karas 4229784f35SKrzysztof Karas Returns: 4329784f35SKrzysztof Karas On success, 0 is returned. On error, -1 is returned. 4429784f35SKrzysztof Karas """ 45bbf8dfb7SEugene Kobyak client = args.client 46bbf8dfb7SEugene Kobyak param_names = ['queue_depth', 'time_in_sec', 'workload_type', 'io_size', 'rw_percentage'] 47bbf8dfb7SEugene Kobyak params = {name: getattr(args, name) for name in param_names if getattr(args, name, None)} 4829784f35SKrzysztof Karas return client.call('perform_tests', params) 4929784f35SKrzysztof Karas 5029784f35SKrzysztof Karas 5129784f35SKrzysztof Karasif __name__ == "__main__": 5229784f35SKrzysztof Karas parser = argparse.ArgumentParser( 5329784f35SKrzysztof Karas description='SPDK RPC command line interface. NOTE: spdk/python is expected in PYTHONPATH') 5429784f35SKrzysztof Karas parser.add_argument('-s', dest='server_addr', 5529784f35SKrzysztof Karas help='RPC domain socket path or IP address', default='/var/tmp/spdk.sock') 5629784f35SKrzysztof Karas parser.add_argument('-p', dest='port', 5729784f35SKrzysztof Karas help='RPC port number (if server_addr is IP address)', 5829784f35SKrzysztof Karas default=5260, type=int) 5929784f35SKrzysztof Karas parser.add_argument('-t', dest='timeout', 6029784f35SKrzysztof Karas help='Timeout as a floating point number expressed in seconds waiting for response. Default: 60.0', 6129784f35SKrzysztof Karas default=60.0, type=float) 6229784f35SKrzysztof Karas parser.add_argument('-v', dest='verbose', action='store_const', const="INFO", 6329784f35SKrzysztof Karas help='Set verbose mode to INFO', default="ERROR") 6429784f35SKrzysztof Karas parser.add_argument('--verbose', dest='verbose', choices=['DEBUG', 'INFO', 'ERROR'], 6529784f35SKrzysztof Karas help="""Set verbose level. """) 6629784f35SKrzysztof Karas subparsers = parser.add_subparsers(help='RPC methods') 6729784f35SKrzysztof Karas 6829784f35SKrzysztof Karas def perform_tests(args): 69bbf8dfb7SEugene Kobyak print_dict(perform_tests_func(args)) 7029784f35SKrzysztof Karas 71bbf8dfb7SEugene Kobyak perform_tests_help_string = ''' 72bbf8dfb7SEugene Kobyak Perform bdevperf tests 73bbf8dfb7SEugene Kobyak All parameters are optional. 74bbf8dfb7SEugene Kobyak If any parameter provided it will overwrite ones from prior run or command line. 75bbf8dfb7SEugene Kobyak If job config file was used no parameter should be provided. 76bbf8dfb7SEugene Kobyak ''' 77bbf8dfb7SEugene Kobyak p = subparsers.add_parser('perform_tests', help=perform_tests_help_string) 78bbf8dfb7SEugene Kobyak p.add_argument('-q', dest="queue_depth", help='io depth', type=int) 79bbf8dfb7SEugene Kobyak p.add_argument('-o', dest="io_size", help='Size in bytes', type=str) 80bbf8dfb7SEugene Kobyak p.add_argument('-t', dest="time_in_sec", help='Time in seconds', type=int) 81bbf8dfb7SEugene Kobyak p.add_argument('-M', dest="rw_percentage", help='rwmixread (100 for reads, 0 for writes)', 82bbf8dfb7SEugene Kobyak type=int, choices=range(0, 101), metavar="[0-100]") 83bbf8dfb7SEugene Kobyak p.add_argument('-w', dest="workload_type", choices=PATTERN_TYPES_STR, type=str.lower, 84bbf8dfb7SEugene Kobyak help=f'io pattern type, must be one of {PATTERN_TYPES_STR}',) 8529784f35SKrzysztof Karas p.set_defaults(func=perform_tests) 8629784f35SKrzysztof Karas 8729784f35SKrzysztof Karas def call_rpc_func(args): 8829784f35SKrzysztof Karas try: 8929784f35SKrzysztof Karas args.func(args) 9029784f35SKrzysztof Karas except JSONRPCException as ex: 9129784f35SKrzysztof Karas print(ex.message) 9229784f35SKrzysztof Karas exit(1) 9329784f35SKrzysztof Karas 9429784f35SKrzysztof Karas def execute_script(parser, client, fd): 9529784f35SKrzysztof Karas for rpc_call in map(str.rstrip, fd): 9629784f35SKrzysztof Karas if not rpc_call.strip(): 9729784f35SKrzysztof Karas continue 9829784f35SKrzysztof Karas args = parser.parse_args(shlex.split(rpc_call)) 9929784f35SKrzysztof Karas args.client = client 10029784f35SKrzysztof Karas call_rpc_func(args) 10129784f35SKrzysztof Karas 10229784f35SKrzysztof Karas args = parser.parse_args() 103db026688SMarcin Spiewak if args.time_in_sec is not None: 104db026688SMarcin Spiewak args.timeout = max(float(args.time_in_sec + 5), args.timeout) 10529784f35SKrzysztof Karas args.client = rpc.client.JSONRPCClient(args.server_addr, args.port, args.timeout, log_level=getattr(logging, args.verbose.upper())) 10629784f35SKrzysztof Karas if hasattr(args, 'func'): 10729784f35SKrzysztof Karas call_rpc_func(args) 10829784f35SKrzysztof Karas elif sys.stdin.isatty(): 10929784f35SKrzysztof Karas # No arguments and no data piped through stdin 11029784f35SKrzysztof Karas parser.print_help() 11129784f35SKrzysztof Karas exit(1) 11229784f35SKrzysztof Karas else: 11329784f35SKrzysztof Karas execute_script(parser, args.client, sys.stdin) 114