18c2ecf20Sopenharmony_ci#!/usr/bin/env python3 28c2ecf20Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0 38c2ecf20Sopenharmony_ci# 48c2ecf20Sopenharmony_ci# Program to allow users to fuzz test Hyper-V drivers 58c2ecf20Sopenharmony_ci# by interfacing with Hyper-V debugfs attributes. 68c2ecf20Sopenharmony_ci# Current test methods available: 78c2ecf20Sopenharmony_ci# 1. delay testing 88c2ecf20Sopenharmony_ci# 98c2ecf20Sopenharmony_ci# Current file/directory structure of hyper-V debugfs: 108c2ecf20Sopenharmony_ci# /sys/kernel/debug/hyperv/UUID 118c2ecf20Sopenharmony_ci# /sys/kernel/debug/hyperv/UUID/<test-state filename> 128c2ecf20Sopenharmony_ci# /sys/kernel/debug/hyperv/UUID/<test-method sub-directory> 138c2ecf20Sopenharmony_ci# 148c2ecf20Sopenharmony_ci# author: Branden Bonaby <brandonbonaby94@gmail.com> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ciimport os 178c2ecf20Sopenharmony_ciimport cmd 188c2ecf20Sopenharmony_ciimport argparse 198c2ecf20Sopenharmony_ciimport glob 208c2ecf20Sopenharmony_cifrom argparse import RawDescriptionHelpFormatter 218c2ecf20Sopenharmony_cifrom argparse import RawTextHelpFormatter 228c2ecf20Sopenharmony_cifrom enum import Enum 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci# Do not change unless, you change the debugfs attributes 258c2ecf20Sopenharmony_ci# in /drivers/hv/debugfs.c. All fuzz testing 268c2ecf20Sopenharmony_ci# attributes will start with "fuzz_test". 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci# debugfs path for hyperv must exist before proceeding 298c2ecf20Sopenharmony_cidebugfs_hyperv_path = "/sys/kernel/debug/hyperv" 308c2ecf20Sopenharmony_ciif not os.path.isdir(debugfs_hyperv_path): 318c2ecf20Sopenharmony_ci print("{} doesn't exist/check permissions".format(debugfs_hyperv_path)) 328c2ecf20Sopenharmony_ci exit(-1) 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ciclass dev_state(Enum): 358c2ecf20Sopenharmony_ci off = 0 368c2ecf20Sopenharmony_ci on = 1 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci# File names, that correspond to the files created in 398c2ecf20Sopenharmony_ci# /drivers/hv/debugfs.c 408c2ecf20Sopenharmony_ciclass f_names(Enum): 418c2ecf20Sopenharmony_ci state_f = "fuzz_test_state" 428c2ecf20Sopenharmony_ci buff_f = "fuzz_test_buffer_interrupt_delay" 438c2ecf20Sopenharmony_ci mess_f = "fuzz_test_message_delay" 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci# Both single_actions and all_actions are used 468c2ecf20Sopenharmony_ci# for error checking and to allow for some subparser 478c2ecf20Sopenharmony_ci# names to be abbreviated. Do not abbreviate the 488c2ecf20Sopenharmony_ci# test method names, as it will become less intuitive 498c2ecf20Sopenharmony_ci# as to what the user can do. If you do decide to 508c2ecf20Sopenharmony_ci# abbreviate the test method name, make sure the main 518c2ecf20Sopenharmony_ci# function reflects this change. 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ciall_actions = [ 548c2ecf20Sopenharmony_ci "disable_all", 558c2ecf20Sopenharmony_ci "D", 568c2ecf20Sopenharmony_ci "enable_all", 578c2ecf20Sopenharmony_ci "view_all", 588c2ecf20Sopenharmony_ci "V" 598c2ecf20Sopenharmony_ci] 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_cisingle_actions = [ 628c2ecf20Sopenharmony_ci "disable_single", 638c2ecf20Sopenharmony_ci "d", 648c2ecf20Sopenharmony_ci "enable_single", 658c2ecf20Sopenharmony_ci "view_single", 668c2ecf20Sopenharmony_ci "v" 678c2ecf20Sopenharmony_ci] 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_cidef main(): 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci file_map = recursive_file_lookup(debugfs_hyperv_path, dict()) 728c2ecf20Sopenharmony_ci args = parse_args() 738c2ecf20Sopenharmony_ci if (not args.action): 748c2ecf20Sopenharmony_ci print ("Error, no options selected...exiting") 758c2ecf20Sopenharmony_ci exit(-1) 768c2ecf20Sopenharmony_ci arg_set = { k for (k,v) in vars(args).items() if v and k != "action" } 778c2ecf20Sopenharmony_ci arg_set.add(args.action) 788c2ecf20Sopenharmony_ci path = args.path if "path" in arg_set else None 798c2ecf20Sopenharmony_ci if (path and path[-1] == "/"): 808c2ecf20Sopenharmony_ci path = path[:-1] 818c2ecf20Sopenharmony_ci validate_args_path(path, arg_set, file_map) 828c2ecf20Sopenharmony_ci if (path and "enable_single" in arg_set): 838c2ecf20Sopenharmony_ci state_path = locate_state(path, file_map) 848c2ecf20Sopenharmony_ci set_test_state(state_path, dev_state.on.value, args.quiet) 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci # Use subparsers as the key for different actions 878c2ecf20Sopenharmony_ci if ("delay" in arg_set): 888c2ecf20Sopenharmony_ci validate_delay_values(args.delay_time) 898c2ecf20Sopenharmony_ci if (args.enable_all): 908c2ecf20Sopenharmony_ci set_delay_all_devices(file_map, args.delay_time, 918c2ecf20Sopenharmony_ci args.quiet) 928c2ecf20Sopenharmony_ci else: 938c2ecf20Sopenharmony_ci set_delay_values(path, file_map, args.delay_time, 948c2ecf20Sopenharmony_ci args.quiet) 958c2ecf20Sopenharmony_ci elif ("disable_all" in arg_set or "D" in arg_set): 968c2ecf20Sopenharmony_ci disable_all_testing(file_map) 978c2ecf20Sopenharmony_ci elif ("disable_single" in arg_set or "d" in arg_set): 988c2ecf20Sopenharmony_ci disable_testing_single_device(path, file_map) 998c2ecf20Sopenharmony_ci elif ("view_all" in arg_set or "V" in arg_set): 1008c2ecf20Sopenharmony_ci get_all_devices_test_status(file_map) 1018c2ecf20Sopenharmony_ci elif ("view_single" in arg_set or "v" in arg_set): 1028c2ecf20Sopenharmony_ci get_device_test_values(path, file_map) 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci# Get the state location 1058c2ecf20Sopenharmony_cidef locate_state(device, file_map): 1068c2ecf20Sopenharmony_ci return file_map[device][f_names.state_f.value] 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci# Validate delay values to make sure they are acceptable to 1098c2ecf20Sopenharmony_ci# enable delays on a device 1108c2ecf20Sopenharmony_cidef validate_delay_values(delay): 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci if (delay[0] == -1 and delay[1] == -1): 1138c2ecf20Sopenharmony_ci print("\nError, At least 1 value must be greater than 0") 1148c2ecf20Sopenharmony_ci exit(-1) 1158c2ecf20Sopenharmony_ci for i in delay: 1168c2ecf20Sopenharmony_ci if (i < -1 or i == 0 or i > 1000): 1178c2ecf20Sopenharmony_ci print("\nError, Values must be equal to -1 " 1188c2ecf20Sopenharmony_ci "or be > 0 and <= 1000") 1198c2ecf20Sopenharmony_ci exit(-1) 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci# Validate argument path 1228c2ecf20Sopenharmony_cidef validate_args_path(path, arg_set, file_map): 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci if (not path and any(element in arg_set for element in single_actions)): 1258c2ecf20Sopenharmony_ci print("Error, path (-p) REQUIRED for the specified option. " 1268c2ecf20Sopenharmony_ci "Use (-h) to check usage.") 1278c2ecf20Sopenharmony_ci exit(-1) 1288c2ecf20Sopenharmony_ci elif (path and any(item in arg_set for item in all_actions)): 1298c2ecf20Sopenharmony_ci print("Error, path (-p) NOT REQUIRED for the specified option. " 1308c2ecf20Sopenharmony_ci "Use (-h) to check usage." ) 1318c2ecf20Sopenharmony_ci exit(-1) 1328c2ecf20Sopenharmony_ci elif (path not in file_map and any(item in arg_set 1338c2ecf20Sopenharmony_ci for item in single_actions)): 1348c2ecf20Sopenharmony_ci print("Error, path '{}' not a valid vmbus device".format(path)) 1358c2ecf20Sopenharmony_ci exit(-1) 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci# display Testing status of single device 1388c2ecf20Sopenharmony_cidef get_device_test_values(path, file_map): 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci for name in file_map[path]: 1418c2ecf20Sopenharmony_ci file_location = file_map[path][name] 1428c2ecf20Sopenharmony_ci print( name + " = " + str(read_test_files(file_location))) 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci# Create a map of the vmbus devices and their associated files 1458c2ecf20Sopenharmony_ci# [key=device, value = [key = filename, value = file path]] 1468c2ecf20Sopenharmony_cidef recursive_file_lookup(path, file_map): 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci for f_path in glob.iglob(path + '**/*'): 1498c2ecf20Sopenharmony_ci if (os.path.isfile(f_path)): 1508c2ecf20Sopenharmony_ci if (f_path.rsplit("/",2)[0] == debugfs_hyperv_path): 1518c2ecf20Sopenharmony_ci directory = f_path.rsplit("/",1)[0] 1528c2ecf20Sopenharmony_ci else: 1538c2ecf20Sopenharmony_ci directory = f_path.rsplit("/",2)[0] 1548c2ecf20Sopenharmony_ci f_name = f_path.split("/")[-1] 1558c2ecf20Sopenharmony_ci if (file_map.get(directory)): 1568c2ecf20Sopenharmony_ci file_map[directory].update({f_name:f_path}) 1578c2ecf20Sopenharmony_ci else: 1588c2ecf20Sopenharmony_ci file_map[directory] = {f_name:f_path} 1598c2ecf20Sopenharmony_ci elif (os.path.isdir(f_path)): 1608c2ecf20Sopenharmony_ci recursive_file_lookup(f_path,file_map) 1618c2ecf20Sopenharmony_ci return file_map 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci# display Testing state of devices 1648c2ecf20Sopenharmony_cidef get_all_devices_test_status(file_map): 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci for device in file_map: 1678c2ecf20Sopenharmony_ci if (get_test_state(locate_state(device, file_map)) == 1): 1688c2ecf20Sopenharmony_ci print("Testing = ON for: {}" 1698c2ecf20Sopenharmony_ci .format(device.split("/")[5])) 1708c2ecf20Sopenharmony_ci else: 1718c2ecf20Sopenharmony_ci print("Testing = OFF for: {}" 1728c2ecf20Sopenharmony_ci .format(device.split("/")[5])) 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci# read the vmbus device files, path must be absolute path before calling 1758c2ecf20Sopenharmony_cidef read_test_files(path): 1768c2ecf20Sopenharmony_ci try: 1778c2ecf20Sopenharmony_ci with open(path,"r") as f: 1788c2ecf20Sopenharmony_ci file_value = f.readline().strip() 1798c2ecf20Sopenharmony_ci return int(file_value) 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci except IOError as e: 1828c2ecf20Sopenharmony_ci errno, strerror = e.args 1838c2ecf20Sopenharmony_ci print("I/O error({0}): {1} on file {2}" 1848c2ecf20Sopenharmony_ci .format(errno, strerror, path)) 1858c2ecf20Sopenharmony_ci exit(-1) 1868c2ecf20Sopenharmony_ci except ValueError: 1878c2ecf20Sopenharmony_ci print ("Element to int conversion error in: \n{}".format(path)) 1888c2ecf20Sopenharmony_ci exit(-1) 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci# writing to vmbus device files, path must be absolute path before calling 1918c2ecf20Sopenharmony_cidef write_test_files(path, value): 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci try: 1948c2ecf20Sopenharmony_ci with open(path,"w") as f: 1958c2ecf20Sopenharmony_ci f.write("{}".format(value)) 1968c2ecf20Sopenharmony_ci except IOError as e: 1978c2ecf20Sopenharmony_ci errno, strerror = e.args 1988c2ecf20Sopenharmony_ci print("I/O error({0}): {1} on file {2}" 1998c2ecf20Sopenharmony_ci .format(errno, strerror, path)) 2008c2ecf20Sopenharmony_ci exit(-1) 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci# set testing state of device 2038c2ecf20Sopenharmony_cidef set_test_state(state_path, state_value, quiet): 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci write_test_files(state_path, state_value) 2068c2ecf20Sopenharmony_ci if (get_test_state(state_path) == 1): 2078c2ecf20Sopenharmony_ci if (not quiet): 2088c2ecf20Sopenharmony_ci print("Testing = ON for device: {}" 2098c2ecf20Sopenharmony_ci .format(state_path.split("/")[5])) 2108c2ecf20Sopenharmony_ci else: 2118c2ecf20Sopenharmony_ci if (not quiet): 2128c2ecf20Sopenharmony_ci print("Testing = OFF for device: {}" 2138c2ecf20Sopenharmony_ci .format(state_path.split("/")[5])) 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci# get testing state of device 2168c2ecf20Sopenharmony_cidef get_test_state(state_path): 2178c2ecf20Sopenharmony_ci #state == 1 - test = ON 2188c2ecf20Sopenharmony_ci #state == 0 - test = OFF 2198c2ecf20Sopenharmony_ci return read_test_files(state_path) 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci# write 1 - 1000 microseconds, into a single device using the 2228c2ecf20Sopenharmony_ci# fuzz_test_buffer_interrupt_delay and fuzz_test_message_delay 2238c2ecf20Sopenharmony_ci# debugfs attributes 2248c2ecf20Sopenharmony_cidef set_delay_values(device, file_map, delay_length, quiet): 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci try: 2278c2ecf20Sopenharmony_ci interrupt = file_map[device][f_names.buff_f.value] 2288c2ecf20Sopenharmony_ci message = file_map[device][f_names.mess_f.value] 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci # delay[0]- buffer interrupt delay, delay[1]- message delay 2318c2ecf20Sopenharmony_ci if (delay_length[0] >= 0 and delay_length[0] <= 1000): 2328c2ecf20Sopenharmony_ci write_test_files(interrupt, delay_length[0]) 2338c2ecf20Sopenharmony_ci if (delay_length[1] >= 0 and delay_length[1] <= 1000): 2348c2ecf20Sopenharmony_ci write_test_files(message, delay_length[1]) 2358c2ecf20Sopenharmony_ci if (not quiet): 2368c2ecf20Sopenharmony_ci print("Buffer delay testing = {} for: {}" 2378c2ecf20Sopenharmony_ci .format(read_test_files(interrupt), 2388c2ecf20Sopenharmony_ci interrupt.split("/")[5])) 2398c2ecf20Sopenharmony_ci print("Message delay testing = {} for: {}" 2408c2ecf20Sopenharmony_ci .format(read_test_files(message), 2418c2ecf20Sopenharmony_ci message.split("/")[5])) 2428c2ecf20Sopenharmony_ci except IOError as e: 2438c2ecf20Sopenharmony_ci errno, strerror = e.args 2448c2ecf20Sopenharmony_ci print("I/O error({0}): {1} on files {2}{3}" 2458c2ecf20Sopenharmony_ci .format(errno, strerror, interrupt, message)) 2468c2ecf20Sopenharmony_ci exit(-1) 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci# enabling delay testing on all devices 2498c2ecf20Sopenharmony_cidef set_delay_all_devices(file_map, delay, quiet): 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci for device in (file_map): 2528c2ecf20Sopenharmony_ci set_test_state(locate_state(device, file_map), 2538c2ecf20Sopenharmony_ci dev_state.on.value, 2548c2ecf20Sopenharmony_ci quiet) 2558c2ecf20Sopenharmony_ci set_delay_values(device, file_map, delay, quiet) 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci# disable all testing on a SINGLE device. 2588c2ecf20Sopenharmony_cidef disable_testing_single_device(device, file_map): 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci for name in file_map[device]: 2618c2ecf20Sopenharmony_ci file_location = file_map[device][name] 2628c2ecf20Sopenharmony_ci write_test_files(file_location, dev_state.off.value) 2638c2ecf20Sopenharmony_ci print("ALL testing now OFF for {}".format(device.split("/")[-1])) 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci# disable all testing on ALL devices 2668c2ecf20Sopenharmony_cidef disable_all_testing(file_map): 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci for device in file_map: 2698c2ecf20Sopenharmony_ci disable_testing_single_device(device, file_map) 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_cidef parse_args(): 2728c2ecf20Sopenharmony_ci parser = argparse.ArgumentParser(prog = "vmbus_testing",usage ="\n" 2738c2ecf20Sopenharmony_ci "%(prog)s [delay] [-h] [-e|-E] -t [-p]\n" 2748c2ecf20Sopenharmony_ci "%(prog)s [view_all | V] [-h]\n" 2758c2ecf20Sopenharmony_ci "%(prog)s [disable_all | D] [-h]\n" 2768c2ecf20Sopenharmony_ci "%(prog)s [disable_single | d] [-h|-p]\n" 2778c2ecf20Sopenharmony_ci "%(prog)s [view_single | v] [-h|-p]\n" 2788c2ecf20Sopenharmony_ci "%(prog)s --version\n", 2798c2ecf20Sopenharmony_ci description = "\nUse lsvmbus to get vmbus device type " 2808c2ecf20Sopenharmony_ci "information.\n" "\nThe debugfs root path is " 2818c2ecf20Sopenharmony_ci "/sys/kernel/debug/hyperv", 2828c2ecf20Sopenharmony_ci formatter_class = RawDescriptionHelpFormatter) 2838c2ecf20Sopenharmony_ci subparsers = parser.add_subparsers(dest = "action") 2848c2ecf20Sopenharmony_ci parser.add_argument("--version", action = "version", 2858c2ecf20Sopenharmony_ci version = '%(prog)s 0.1.0') 2868c2ecf20Sopenharmony_ci parser.add_argument("-q","--quiet", action = "store_true", 2878c2ecf20Sopenharmony_ci help = "silence none important test messages." 2888c2ecf20Sopenharmony_ci " This will only work when enabling testing" 2898c2ecf20Sopenharmony_ci " on a device.") 2908c2ecf20Sopenharmony_ci # Use the path parser to hold the --path attribute so it can 2918c2ecf20Sopenharmony_ci # be shared between subparsers. Also do the same for the state 2928c2ecf20Sopenharmony_ci # parser, as all testing methods will use --enable_all and 2938c2ecf20Sopenharmony_ci # enable_single. 2948c2ecf20Sopenharmony_ci path_parser = argparse.ArgumentParser(add_help=False) 2958c2ecf20Sopenharmony_ci path_parser.add_argument("-p","--path", metavar = "", 2968c2ecf20Sopenharmony_ci help = "Debugfs path to a vmbus device. The path " 2978c2ecf20Sopenharmony_ci "must be the absolute path to the device.") 2988c2ecf20Sopenharmony_ci state_parser = argparse.ArgumentParser(add_help=False) 2998c2ecf20Sopenharmony_ci state_group = state_parser.add_mutually_exclusive_group(required = True) 3008c2ecf20Sopenharmony_ci state_group.add_argument("-E", "--enable_all", action = "store_const", 3018c2ecf20Sopenharmony_ci const = "enable_all", 3028c2ecf20Sopenharmony_ci help = "Enable the specified test type " 3038c2ecf20Sopenharmony_ci "on ALL vmbus devices.") 3048c2ecf20Sopenharmony_ci state_group.add_argument("-e", "--enable_single", 3058c2ecf20Sopenharmony_ci action = "store_const", 3068c2ecf20Sopenharmony_ci const = "enable_single", 3078c2ecf20Sopenharmony_ci help = "Enable the specified test type on a " 3088c2ecf20Sopenharmony_ci "SINGLE vmbus device.") 3098c2ecf20Sopenharmony_ci parser_delay = subparsers.add_parser("delay", 3108c2ecf20Sopenharmony_ci parents = [state_parser, path_parser], 3118c2ecf20Sopenharmony_ci help = "Delay the ring buffer interrupt or the " 3128c2ecf20Sopenharmony_ci "ring buffer message reads in microseconds.", 3138c2ecf20Sopenharmony_ci prog = "vmbus_testing", 3148c2ecf20Sopenharmony_ci usage = "%(prog)s [-h]\n" 3158c2ecf20Sopenharmony_ci "%(prog)s -E -t [value] [value]\n" 3168c2ecf20Sopenharmony_ci "%(prog)s -e -t [value] [value] -p", 3178c2ecf20Sopenharmony_ci description = "Delay the ring buffer interrupt for " 3188c2ecf20Sopenharmony_ci "vmbus devices, or delay the ring buffer message " 3198c2ecf20Sopenharmony_ci "reads for vmbus devices (both in microseconds). This " 3208c2ecf20Sopenharmony_ci "is only on the host to guest channel.") 3218c2ecf20Sopenharmony_ci parser_delay.add_argument("-t", "--delay_time", metavar = "", nargs = 2, 3228c2ecf20Sopenharmony_ci type = check_range, default =[0,0], required = (True), 3238c2ecf20Sopenharmony_ci help = "Set [buffer] & [message] delay time. " 3248c2ecf20Sopenharmony_ci "Value constraints: -1 == value " 3258c2ecf20Sopenharmony_ci "or 0 < value <= 1000.\n" 3268c2ecf20Sopenharmony_ci "Use -1 to keep the previous value for that delay " 3278c2ecf20Sopenharmony_ci "type, or a value > 0 <= 1000 to change the delay " 3288c2ecf20Sopenharmony_ci "time.") 3298c2ecf20Sopenharmony_ci parser_dis_all = subparsers.add_parser("disable_all", 3308c2ecf20Sopenharmony_ci aliases = ['D'], prog = "vmbus_testing", 3318c2ecf20Sopenharmony_ci usage = "%(prog)s [disable_all | D] -h\n" 3328c2ecf20Sopenharmony_ci "%(prog)s [disable_all | D]\n", 3338c2ecf20Sopenharmony_ci help = "Disable ALL testing on ALL vmbus devices.", 3348c2ecf20Sopenharmony_ci description = "Disable ALL testing on ALL vmbus " 3358c2ecf20Sopenharmony_ci "devices.") 3368c2ecf20Sopenharmony_ci parser_dis_single = subparsers.add_parser("disable_single", 3378c2ecf20Sopenharmony_ci aliases = ['d'], 3388c2ecf20Sopenharmony_ci parents = [path_parser], prog = "vmbus_testing", 3398c2ecf20Sopenharmony_ci usage = "%(prog)s [disable_single | d] -h\n" 3408c2ecf20Sopenharmony_ci "%(prog)s [disable_single | d] -p\n", 3418c2ecf20Sopenharmony_ci help = "Disable ALL testing on a SINGLE vmbus device.", 3428c2ecf20Sopenharmony_ci description = "Disable ALL testing on a SINGLE vmbus " 3438c2ecf20Sopenharmony_ci "device.") 3448c2ecf20Sopenharmony_ci parser_view_all = subparsers.add_parser("view_all", aliases = ['V'], 3458c2ecf20Sopenharmony_ci help = "View the test state for ALL vmbus devices.", 3468c2ecf20Sopenharmony_ci prog = "vmbus_testing", 3478c2ecf20Sopenharmony_ci usage = "%(prog)s [view_all | V] -h\n" 3488c2ecf20Sopenharmony_ci "%(prog)s [view_all | V]\n", 3498c2ecf20Sopenharmony_ci description = "This shows the test state for ALL the " 3508c2ecf20Sopenharmony_ci "vmbus devices.") 3518c2ecf20Sopenharmony_ci parser_view_single = subparsers.add_parser("view_single", 3528c2ecf20Sopenharmony_ci aliases = ['v'],parents = [path_parser], 3538c2ecf20Sopenharmony_ci help = "View the test values for a SINGLE vmbus " 3548c2ecf20Sopenharmony_ci "device.", 3558c2ecf20Sopenharmony_ci description = "This shows the test values for a SINGLE " 3568c2ecf20Sopenharmony_ci "vmbus device.", prog = "vmbus_testing", 3578c2ecf20Sopenharmony_ci usage = "%(prog)s [view_single | v] -h\n" 3588c2ecf20Sopenharmony_ci "%(prog)s [view_single | v] -p") 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci return parser.parse_args() 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci# value checking for range checking input in parser 3638c2ecf20Sopenharmony_cidef check_range(arg1): 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci try: 3668c2ecf20Sopenharmony_ci val = int(arg1) 3678c2ecf20Sopenharmony_ci except ValueError as err: 3688c2ecf20Sopenharmony_ci raise argparse.ArgumentTypeError(str(err)) 3698c2ecf20Sopenharmony_ci if val < -1 or val > 1000: 3708c2ecf20Sopenharmony_ci message = ("\n\nvalue must be -1 or 0 < value <= 1000. " 3718c2ecf20Sopenharmony_ci "Value program received: {}\n").format(val) 3728c2ecf20Sopenharmony_ci raise argparse.ArgumentTypeError(message) 3738c2ecf20Sopenharmony_ci return val 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ciif __name__ == "__main__": 3768c2ecf20Sopenharmony_ci main() 377