162306a36Sopenharmony_ci#!/usr/bin/env python3 262306a36Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0 362306a36Sopenharmony_ci# 462306a36Sopenharmony_ci# Program to allow users to fuzz test Hyper-V drivers 562306a36Sopenharmony_ci# by interfacing with Hyper-V debugfs attributes. 662306a36Sopenharmony_ci# Current test methods available: 762306a36Sopenharmony_ci# 1. delay testing 862306a36Sopenharmony_ci# 962306a36Sopenharmony_ci# Current file/directory structure of hyper-V debugfs: 1062306a36Sopenharmony_ci# /sys/kernel/debug/hyperv/UUID 1162306a36Sopenharmony_ci# /sys/kernel/debug/hyperv/UUID/<test-state filename> 1262306a36Sopenharmony_ci# /sys/kernel/debug/hyperv/UUID/<test-method sub-directory> 1362306a36Sopenharmony_ci# 1462306a36Sopenharmony_ci# author: Branden Bonaby <brandonbonaby94@gmail.com> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ciimport os 1762306a36Sopenharmony_ciimport cmd 1862306a36Sopenharmony_ciimport argparse 1962306a36Sopenharmony_ciimport glob 2062306a36Sopenharmony_cifrom argparse import RawDescriptionHelpFormatter 2162306a36Sopenharmony_cifrom argparse import RawTextHelpFormatter 2262306a36Sopenharmony_cifrom enum import Enum 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci# Do not change unless, you change the debugfs attributes 2562306a36Sopenharmony_ci# in /drivers/hv/debugfs.c. All fuzz testing 2662306a36Sopenharmony_ci# attributes will start with "fuzz_test". 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci# debugfs path for hyperv must exist before proceeding 2962306a36Sopenharmony_cidebugfs_hyperv_path = "/sys/kernel/debug/hyperv" 3062306a36Sopenharmony_ciif not os.path.isdir(debugfs_hyperv_path): 3162306a36Sopenharmony_ci print("{} doesn't exist/check permissions".format(debugfs_hyperv_path)) 3262306a36Sopenharmony_ci exit(-1) 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ciclass dev_state(Enum): 3562306a36Sopenharmony_ci off = 0 3662306a36Sopenharmony_ci on = 1 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci# File names, that correspond to the files created in 3962306a36Sopenharmony_ci# /drivers/hv/debugfs.c 4062306a36Sopenharmony_ciclass f_names(Enum): 4162306a36Sopenharmony_ci state_f = "fuzz_test_state" 4262306a36Sopenharmony_ci buff_f = "fuzz_test_buffer_interrupt_delay" 4362306a36Sopenharmony_ci mess_f = "fuzz_test_message_delay" 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci# Both single_actions and all_actions are used 4662306a36Sopenharmony_ci# for error checking and to allow for some subparser 4762306a36Sopenharmony_ci# names to be abbreviated. Do not abbreviate the 4862306a36Sopenharmony_ci# test method names, as it will become less intuitive 4962306a36Sopenharmony_ci# as to what the user can do. If you do decide to 5062306a36Sopenharmony_ci# abbreviate the test method name, make sure the main 5162306a36Sopenharmony_ci# function reflects this change. 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ciall_actions = [ 5462306a36Sopenharmony_ci "disable_all", 5562306a36Sopenharmony_ci "D", 5662306a36Sopenharmony_ci "enable_all", 5762306a36Sopenharmony_ci "view_all", 5862306a36Sopenharmony_ci "V" 5962306a36Sopenharmony_ci] 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_cisingle_actions = [ 6262306a36Sopenharmony_ci "disable_single", 6362306a36Sopenharmony_ci "d", 6462306a36Sopenharmony_ci "enable_single", 6562306a36Sopenharmony_ci "view_single", 6662306a36Sopenharmony_ci "v" 6762306a36Sopenharmony_ci] 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_cidef main(): 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci file_map = recursive_file_lookup(debugfs_hyperv_path, dict()) 7262306a36Sopenharmony_ci args = parse_args() 7362306a36Sopenharmony_ci if (not args.action): 7462306a36Sopenharmony_ci print ("Error, no options selected...exiting") 7562306a36Sopenharmony_ci exit(-1) 7662306a36Sopenharmony_ci arg_set = { k for (k,v) in vars(args).items() if v and k != "action" } 7762306a36Sopenharmony_ci arg_set.add(args.action) 7862306a36Sopenharmony_ci path = args.path if "path" in arg_set else None 7962306a36Sopenharmony_ci if (path and path[-1] == "/"): 8062306a36Sopenharmony_ci path = path[:-1] 8162306a36Sopenharmony_ci validate_args_path(path, arg_set, file_map) 8262306a36Sopenharmony_ci if (path and "enable_single" in arg_set): 8362306a36Sopenharmony_ci state_path = locate_state(path, file_map) 8462306a36Sopenharmony_ci set_test_state(state_path, dev_state.on.value, args.quiet) 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci # Use subparsers as the key for different actions 8762306a36Sopenharmony_ci if ("delay" in arg_set): 8862306a36Sopenharmony_ci validate_delay_values(args.delay_time) 8962306a36Sopenharmony_ci if (args.enable_all): 9062306a36Sopenharmony_ci set_delay_all_devices(file_map, args.delay_time, 9162306a36Sopenharmony_ci args.quiet) 9262306a36Sopenharmony_ci else: 9362306a36Sopenharmony_ci set_delay_values(path, file_map, args.delay_time, 9462306a36Sopenharmony_ci args.quiet) 9562306a36Sopenharmony_ci elif ("disable_all" in arg_set or "D" in arg_set): 9662306a36Sopenharmony_ci disable_all_testing(file_map) 9762306a36Sopenharmony_ci elif ("disable_single" in arg_set or "d" in arg_set): 9862306a36Sopenharmony_ci disable_testing_single_device(path, file_map) 9962306a36Sopenharmony_ci elif ("view_all" in arg_set or "V" in arg_set): 10062306a36Sopenharmony_ci get_all_devices_test_status(file_map) 10162306a36Sopenharmony_ci elif ("view_single" in arg_set or "v" in arg_set): 10262306a36Sopenharmony_ci get_device_test_values(path, file_map) 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci# Get the state location 10562306a36Sopenharmony_cidef locate_state(device, file_map): 10662306a36Sopenharmony_ci return file_map[device][f_names.state_f.value] 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci# Validate delay values to make sure they are acceptable to 10962306a36Sopenharmony_ci# enable delays on a device 11062306a36Sopenharmony_cidef validate_delay_values(delay): 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci if (delay[0] == -1 and delay[1] == -1): 11362306a36Sopenharmony_ci print("\nError, At least 1 value must be greater than 0") 11462306a36Sopenharmony_ci exit(-1) 11562306a36Sopenharmony_ci for i in delay: 11662306a36Sopenharmony_ci if (i < -1 or i == 0 or i > 1000): 11762306a36Sopenharmony_ci print("\nError, Values must be equal to -1 " 11862306a36Sopenharmony_ci "or be > 0 and <= 1000") 11962306a36Sopenharmony_ci exit(-1) 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci# Validate argument path 12262306a36Sopenharmony_cidef validate_args_path(path, arg_set, file_map): 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci if (not path and any(element in arg_set for element in single_actions)): 12562306a36Sopenharmony_ci print("Error, path (-p) REQUIRED for the specified option. " 12662306a36Sopenharmony_ci "Use (-h) to check usage.") 12762306a36Sopenharmony_ci exit(-1) 12862306a36Sopenharmony_ci elif (path and any(item in arg_set for item in all_actions)): 12962306a36Sopenharmony_ci print("Error, path (-p) NOT REQUIRED for the specified option. " 13062306a36Sopenharmony_ci "Use (-h) to check usage." ) 13162306a36Sopenharmony_ci exit(-1) 13262306a36Sopenharmony_ci elif (path not in file_map and any(item in arg_set 13362306a36Sopenharmony_ci for item in single_actions)): 13462306a36Sopenharmony_ci print("Error, path '{}' not a valid vmbus device".format(path)) 13562306a36Sopenharmony_ci exit(-1) 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci# display Testing status of single device 13862306a36Sopenharmony_cidef get_device_test_values(path, file_map): 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci for name in file_map[path]: 14162306a36Sopenharmony_ci file_location = file_map[path][name] 14262306a36Sopenharmony_ci print( name + " = " + str(read_test_files(file_location))) 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci# Create a map of the vmbus devices and their associated files 14562306a36Sopenharmony_ci# [key=device, value = [key = filename, value = file path]] 14662306a36Sopenharmony_cidef recursive_file_lookup(path, file_map): 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci for f_path in glob.iglob(path + '**/*'): 14962306a36Sopenharmony_ci if (os.path.isfile(f_path)): 15062306a36Sopenharmony_ci if (f_path.rsplit("/",2)[0] == debugfs_hyperv_path): 15162306a36Sopenharmony_ci directory = f_path.rsplit("/",1)[0] 15262306a36Sopenharmony_ci else: 15362306a36Sopenharmony_ci directory = f_path.rsplit("/",2)[0] 15462306a36Sopenharmony_ci f_name = f_path.split("/")[-1] 15562306a36Sopenharmony_ci if (file_map.get(directory)): 15662306a36Sopenharmony_ci file_map[directory].update({f_name:f_path}) 15762306a36Sopenharmony_ci else: 15862306a36Sopenharmony_ci file_map[directory] = {f_name:f_path} 15962306a36Sopenharmony_ci elif (os.path.isdir(f_path)): 16062306a36Sopenharmony_ci recursive_file_lookup(f_path,file_map) 16162306a36Sopenharmony_ci return file_map 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci# display Testing state of devices 16462306a36Sopenharmony_cidef get_all_devices_test_status(file_map): 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci for device in file_map: 16762306a36Sopenharmony_ci if (get_test_state(locate_state(device, file_map)) == 1): 16862306a36Sopenharmony_ci print("Testing = ON for: {}" 16962306a36Sopenharmony_ci .format(device.split("/")[5])) 17062306a36Sopenharmony_ci else: 17162306a36Sopenharmony_ci print("Testing = OFF for: {}" 17262306a36Sopenharmony_ci .format(device.split("/")[5])) 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci# read the vmbus device files, path must be absolute path before calling 17562306a36Sopenharmony_cidef read_test_files(path): 17662306a36Sopenharmony_ci try: 17762306a36Sopenharmony_ci with open(path,"r") as f: 17862306a36Sopenharmony_ci file_value = f.readline().strip() 17962306a36Sopenharmony_ci return int(file_value) 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci except IOError as e: 18262306a36Sopenharmony_ci errno, strerror = e.args 18362306a36Sopenharmony_ci print("I/O error({0}): {1} on file {2}" 18462306a36Sopenharmony_ci .format(errno, strerror, path)) 18562306a36Sopenharmony_ci exit(-1) 18662306a36Sopenharmony_ci except ValueError: 18762306a36Sopenharmony_ci print ("Element to int conversion error in: \n{}".format(path)) 18862306a36Sopenharmony_ci exit(-1) 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci# writing to vmbus device files, path must be absolute path before calling 19162306a36Sopenharmony_cidef write_test_files(path, value): 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci try: 19462306a36Sopenharmony_ci with open(path,"w") as f: 19562306a36Sopenharmony_ci f.write("{}".format(value)) 19662306a36Sopenharmony_ci except IOError as e: 19762306a36Sopenharmony_ci errno, strerror = e.args 19862306a36Sopenharmony_ci print("I/O error({0}): {1} on file {2}" 19962306a36Sopenharmony_ci .format(errno, strerror, path)) 20062306a36Sopenharmony_ci exit(-1) 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci# set testing state of device 20362306a36Sopenharmony_cidef set_test_state(state_path, state_value, quiet): 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci write_test_files(state_path, state_value) 20662306a36Sopenharmony_ci if (get_test_state(state_path) == 1): 20762306a36Sopenharmony_ci if (not quiet): 20862306a36Sopenharmony_ci print("Testing = ON for device: {}" 20962306a36Sopenharmony_ci .format(state_path.split("/")[5])) 21062306a36Sopenharmony_ci else: 21162306a36Sopenharmony_ci if (not quiet): 21262306a36Sopenharmony_ci print("Testing = OFF for device: {}" 21362306a36Sopenharmony_ci .format(state_path.split("/")[5])) 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci# get testing state of device 21662306a36Sopenharmony_cidef get_test_state(state_path): 21762306a36Sopenharmony_ci #state == 1 - test = ON 21862306a36Sopenharmony_ci #state == 0 - test = OFF 21962306a36Sopenharmony_ci return read_test_files(state_path) 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci# write 1 - 1000 microseconds, into a single device using the 22262306a36Sopenharmony_ci# fuzz_test_buffer_interrupt_delay and fuzz_test_message_delay 22362306a36Sopenharmony_ci# debugfs attributes 22462306a36Sopenharmony_cidef set_delay_values(device, file_map, delay_length, quiet): 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci try: 22762306a36Sopenharmony_ci interrupt = file_map[device][f_names.buff_f.value] 22862306a36Sopenharmony_ci message = file_map[device][f_names.mess_f.value] 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci # delay[0]- buffer interrupt delay, delay[1]- message delay 23162306a36Sopenharmony_ci if (delay_length[0] >= 0 and delay_length[0] <= 1000): 23262306a36Sopenharmony_ci write_test_files(interrupt, delay_length[0]) 23362306a36Sopenharmony_ci if (delay_length[1] >= 0 and delay_length[1] <= 1000): 23462306a36Sopenharmony_ci write_test_files(message, delay_length[1]) 23562306a36Sopenharmony_ci if (not quiet): 23662306a36Sopenharmony_ci print("Buffer delay testing = {} for: {}" 23762306a36Sopenharmony_ci .format(read_test_files(interrupt), 23862306a36Sopenharmony_ci interrupt.split("/")[5])) 23962306a36Sopenharmony_ci print("Message delay testing = {} for: {}" 24062306a36Sopenharmony_ci .format(read_test_files(message), 24162306a36Sopenharmony_ci message.split("/")[5])) 24262306a36Sopenharmony_ci except IOError as e: 24362306a36Sopenharmony_ci errno, strerror = e.args 24462306a36Sopenharmony_ci print("I/O error({0}): {1} on files {2}{3}" 24562306a36Sopenharmony_ci .format(errno, strerror, interrupt, message)) 24662306a36Sopenharmony_ci exit(-1) 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci# enabling delay testing on all devices 24962306a36Sopenharmony_cidef set_delay_all_devices(file_map, delay, quiet): 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci for device in (file_map): 25262306a36Sopenharmony_ci set_test_state(locate_state(device, file_map), 25362306a36Sopenharmony_ci dev_state.on.value, 25462306a36Sopenharmony_ci quiet) 25562306a36Sopenharmony_ci set_delay_values(device, file_map, delay, quiet) 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci# disable all testing on a SINGLE device. 25862306a36Sopenharmony_cidef disable_testing_single_device(device, file_map): 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci for name in file_map[device]: 26162306a36Sopenharmony_ci file_location = file_map[device][name] 26262306a36Sopenharmony_ci write_test_files(file_location, dev_state.off.value) 26362306a36Sopenharmony_ci print("ALL testing now OFF for {}".format(device.split("/")[-1])) 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci# disable all testing on ALL devices 26662306a36Sopenharmony_cidef disable_all_testing(file_map): 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci for device in file_map: 26962306a36Sopenharmony_ci disable_testing_single_device(device, file_map) 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_cidef parse_args(): 27262306a36Sopenharmony_ci parser = argparse.ArgumentParser(prog = "vmbus_testing",usage ="\n" 27362306a36Sopenharmony_ci "%(prog)s [delay] [-h] [-e|-E] -t [-p]\n" 27462306a36Sopenharmony_ci "%(prog)s [view_all | V] [-h]\n" 27562306a36Sopenharmony_ci "%(prog)s [disable_all | D] [-h]\n" 27662306a36Sopenharmony_ci "%(prog)s [disable_single | d] [-h|-p]\n" 27762306a36Sopenharmony_ci "%(prog)s [view_single | v] [-h|-p]\n" 27862306a36Sopenharmony_ci "%(prog)s --version\n", 27962306a36Sopenharmony_ci description = "\nUse lsvmbus to get vmbus device type " 28062306a36Sopenharmony_ci "information.\n" "\nThe debugfs root path is " 28162306a36Sopenharmony_ci "/sys/kernel/debug/hyperv", 28262306a36Sopenharmony_ci formatter_class = RawDescriptionHelpFormatter) 28362306a36Sopenharmony_ci subparsers = parser.add_subparsers(dest = "action") 28462306a36Sopenharmony_ci parser.add_argument("--version", action = "version", 28562306a36Sopenharmony_ci version = '%(prog)s 0.1.0') 28662306a36Sopenharmony_ci parser.add_argument("-q","--quiet", action = "store_true", 28762306a36Sopenharmony_ci help = "silence none important test messages." 28862306a36Sopenharmony_ci " This will only work when enabling testing" 28962306a36Sopenharmony_ci " on a device.") 29062306a36Sopenharmony_ci # Use the path parser to hold the --path attribute so it can 29162306a36Sopenharmony_ci # be shared between subparsers. Also do the same for the state 29262306a36Sopenharmony_ci # parser, as all testing methods will use --enable_all and 29362306a36Sopenharmony_ci # enable_single. 29462306a36Sopenharmony_ci path_parser = argparse.ArgumentParser(add_help=False) 29562306a36Sopenharmony_ci path_parser.add_argument("-p","--path", metavar = "", 29662306a36Sopenharmony_ci help = "Debugfs path to a vmbus device. The path " 29762306a36Sopenharmony_ci "must be the absolute path to the device.") 29862306a36Sopenharmony_ci state_parser = argparse.ArgumentParser(add_help=False) 29962306a36Sopenharmony_ci state_group = state_parser.add_mutually_exclusive_group(required = True) 30062306a36Sopenharmony_ci state_group.add_argument("-E", "--enable_all", action = "store_const", 30162306a36Sopenharmony_ci const = "enable_all", 30262306a36Sopenharmony_ci help = "Enable the specified test type " 30362306a36Sopenharmony_ci "on ALL vmbus devices.") 30462306a36Sopenharmony_ci state_group.add_argument("-e", "--enable_single", 30562306a36Sopenharmony_ci action = "store_const", 30662306a36Sopenharmony_ci const = "enable_single", 30762306a36Sopenharmony_ci help = "Enable the specified test type on a " 30862306a36Sopenharmony_ci "SINGLE vmbus device.") 30962306a36Sopenharmony_ci parser_delay = subparsers.add_parser("delay", 31062306a36Sopenharmony_ci parents = [state_parser, path_parser], 31162306a36Sopenharmony_ci help = "Delay the ring buffer interrupt or the " 31262306a36Sopenharmony_ci "ring buffer message reads in microseconds.", 31362306a36Sopenharmony_ci prog = "vmbus_testing", 31462306a36Sopenharmony_ci usage = "%(prog)s [-h]\n" 31562306a36Sopenharmony_ci "%(prog)s -E -t [value] [value]\n" 31662306a36Sopenharmony_ci "%(prog)s -e -t [value] [value] -p", 31762306a36Sopenharmony_ci description = "Delay the ring buffer interrupt for " 31862306a36Sopenharmony_ci "vmbus devices, or delay the ring buffer message " 31962306a36Sopenharmony_ci "reads for vmbus devices (both in microseconds). This " 32062306a36Sopenharmony_ci "is only on the host to guest channel.") 32162306a36Sopenharmony_ci parser_delay.add_argument("-t", "--delay_time", metavar = "", nargs = 2, 32262306a36Sopenharmony_ci type = check_range, default =[0,0], required = (True), 32362306a36Sopenharmony_ci help = "Set [buffer] & [message] delay time. " 32462306a36Sopenharmony_ci "Value constraints: -1 == value " 32562306a36Sopenharmony_ci "or 0 < value <= 1000.\n" 32662306a36Sopenharmony_ci "Use -1 to keep the previous value for that delay " 32762306a36Sopenharmony_ci "type, or a value > 0 <= 1000 to change the delay " 32862306a36Sopenharmony_ci "time.") 32962306a36Sopenharmony_ci parser_dis_all = subparsers.add_parser("disable_all", 33062306a36Sopenharmony_ci aliases = ['D'], prog = "vmbus_testing", 33162306a36Sopenharmony_ci usage = "%(prog)s [disable_all | D] -h\n" 33262306a36Sopenharmony_ci "%(prog)s [disable_all | D]\n", 33362306a36Sopenharmony_ci help = "Disable ALL testing on ALL vmbus devices.", 33462306a36Sopenharmony_ci description = "Disable ALL testing on ALL vmbus " 33562306a36Sopenharmony_ci "devices.") 33662306a36Sopenharmony_ci parser_dis_single = subparsers.add_parser("disable_single", 33762306a36Sopenharmony_ci aliases = ['d'], 33862306a36Sopenharmony_ci parents = [path_parser], prog = "vmbus_testing", 33962306a36Sopenharmony_ci usage = "%(prog)s [disable_single | d] -h\n" 34062306a36Sopenharmony_ci "%(prog)s [disable_single | d] -p\n", 34162306a36Sopenharmony_ci help = "Disable ALL testing on a SINGLE vmbus device.", 34262306a36Sopenharmony_ci description = "Disable ALL testing on a SINGLE vmbus " 34362306a36Sopenharmony_ci "device.") 34462306a36Sopenharmony_ci parser_view_all = subparsers.add_parser("view_all", aliases = ['V'], 34562306a36Sopenharmony_ci help = "View the test state for ALL vmbus devices.", 34662306a36Sopenharmony_ci prog = "vmbus_testing", 34762306a36Sopenharmony_ci usage = "%(prog)s [view_all | V] -h\n" 34862306a36Sopenharmony_ci "%(prog)s [view_all | V]\n", 34962306a36Sopenharmony_ci description = "This shows the test state for ALL the " 35062306a36Sopenharmony_ci "vmbus devices.") 35162306a36Sopenharmony_ci parser_view_single = subparsers.add_parser("view_single", 35262306a36Sopenharmony_ci aliases = ['v'],parents = [path_parser], 35362306a36Sopenharmony_ci help = "View the test values for a SINGLE vmbus " 35462306a36Sopenharmony_ci "device.", 35562306a36Sopenharmony_ci description = "This shows the test values for a SINGLE " 35662306a36Sopenharmony_ci "vmbus device.", prog = "vmbus_testing", 35762306a36Sopenharmony_ci usage = "%(prog)s [view_single | v] -h\n" 35862306a36Sopenharmony_ci "%(prog)s [view_single | v] -p") 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci return parser.parse_args() 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci# value checking for range checking input in parser 36362306a36Sopenharmony_cidef check_range(arg1): 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci try: 36662306a36Sopenharmony_ci val = int(arg1) 36762306a36Sopenharmony_ci except ValueError as err: 36862306a36Sopenharmony_ci raise argparse.ArgumentTypeError(str(err)) 36962306a36Sopenharmony_ci if val < -1 or val > 1000: 37062306a36Sopenharmony_ci message = ("\n\nvalue must be -1 or 0 < value <= 1000. " 37162306a36Sopenharmony_ci "Value program received: {}\n").format(val) 37262306a36Sopenharmony_ci raise argparse.ArgumentTypeError(message) 37362306a36Sopenharmony_ci return val 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ciif __name__ == "__main__": 37662306a36Sopenharmony_ci main() 377