1c48d8b04SBranden Bonaby#!/usr/bin/env python3 2c48d8b04SBranden Bonaby# SPDX-License-Identifier: GPL-2.0 3c48d8b04SBranden Bonaby# 4c48d8b04SBranden Bonaby# Program to allow users to fuzz test Hyper-V drivers 5c48d8b04SBranden Bonaby# by interfacing with Hyper-V debugfs attributes. 6c48d8b04SBranden Bonaby# Current test methods available: 7c48d8b04SBranden Bonaby# 1. delay testing 8c48d8b04SBranden Bonaby# 9c48d8b04SBranden Bonaby# Current file/directory structure of hyper-V debugfs: 10c48d8b04SBranden Bonaby# /sys/kernel/debug/hyperv/UUID 11c48d8b04SBranden Bonaby# /sys/kernel/debug/hyperv/UUID/<test-state filename> 12c48d8b04SBranden Bonaby# /sys/kernel/debug/hyperv/UUID/<test-method sub-directory> 13c48d8b04SBranden Bonaby# 14c48d8b04SBranden Bonaby# author: Branden Bonaby <brandonbonaby94@gmail.com> 15c48d8b04SBranden Bonaby 16c48d8b04SBranden Bonabyimport os 17c48d8b04SBranden Bonabyimport cmd 18c48d8b04SBranden Bonabyimport argparse 19c48d8b04SBranden Bonabyimport glob 20c48d8b04SBranden Bonabyfrom argparse import RawDescriptionHelpFormatter 21c48d8b04SBranden Bonabyfrom argparse import RawTextHelpFormatter 22c48d8b04SBranden Bonabyfrom enum import Enum 23c48d8b04SBranden Bonaby 24c48d8b04SBranden Bonaby# Do not change unless, you change the debugfs attributes 25c48d8b04SBranden Bonaby# in /drivers/hv/debugfs.c. All fuzz testing 26c48d8b04SBranden Bonaby# attributes will start with "fuzz_test". 27c48d8b04SBranden Bonaby 28c48d8b04SBranden Bonaby# debugfs path for hyperv must exist before proceeding 29c48d8b04SBranden Bonabydebugfs_hyperv_path = "/sys/kernel/debug/hyperv" 30c48d8b04SBranden Bonabyif not os.path.isdir(debugfs_hyperv_path): 31c48d8b04SBranden Bonaby print("{} doesn't exist/check permissions".format(debugfs_hyperv_path)) 32c48d8b04SBranden Bonaby exit(-1) 33c48d8b04SBranden Bonaby 34c48d8b04SBranden Bonabyclass dev_state(Enum): 35c48d8b04SBranden Bonaby off = 0 36c48d8b04SBranden Bonaby on = 1 37c48d8b04SBranden Bonaby 38c48d8b04SBranden Bonaby# File names, that correspond to the files created in 39c48d8b04SBranden Bonaby# /drivers/hv/debugfs.c 40c48d8b04SBranden Bonabyclass f_names(Enum): 41c48d8b04SBranden Bonaby state_f = "fuzz_test_state" 42c48d8b04SBranden Bonaby buff_f = "fuzz_test_buffer_interrupt_delay" 43c48d8b04SBranden Bonaby mess_f = "fuzz_test_message_delay" 44c48d8b04SBranden Bonaby 45c48d8b04SBranden Bonaby# Both single_actions and all_actions are used 46c48d8b04SBranden Bonaby# for error checking and to allow for some subparser 47c48d8b04SBranden Bonaby# names to be abbreviated. Do not abbreviate the 48c48d8b04SBranden Bonaby# test method names, as it will become less intuitive 49c48d8b04SBranden Bonaby# as to what the user can do. If you do decide to 50c48d8b04SBranden Bonaby# abbreviate the test method name, make sure the main 51c48d8b04SBranden Bonaby# function reflects this change. 52c48d8b04SBranden Bonaby 53c48d8b04SBranden Bonabyall_actions = [ 54c48d8b04SBranden Bonaby "disable_all", 55c48d8b04SBranden Bonaby "D", 56c48d8b04SBranden Bonaby "enable_all", 57c48d8b04SBranden Bonaby "view_all", 58c48d8b04SBranden Bonaby "V" 59c48d8b04SBranden Bonaby] 60c48d8b04SBranden Bonaby 61c48d8b04SBranden Bonabysingle_actions = [ 62c48d8b04SBranden Bonaby "disable_single", 63c48d8b04SBranden Bonaby "d", 64c48d8b04SBranden Bonaby "enable_single", 65c48d8b04SBranden Bonaby "view_single", 66c48d8b04SBranden Bonaby "v" 67c48d8b04SBranden Bonaby] 68c48d8b04SBranden Bonaby 69c48d8b04SBranden Bonabydef main(): 70c48d8b04SBranden Bonaby 71c48d8b04SBranden Bonaby file_map = recursive_file_lookup(debugfs_hyperv_path, dict()) 72c48d8b04SBranden Bonaby args = parse_args() 73c48d8b04SBranden Bonaby if (not args.action): 74c48d8b04SBranden Bonaby print ("Error, no options selected...exiting") 75c48d8b04SBranden Bonaby exit(-1) 76c48d8b04SBranden Bonaby arg_set = { k for (k,v) in vars(args).items() if v and k != "action" } 77c48d8b04SBranden Bonaby arg_set.add(args.action) 78c48d8b04SBranden Bonaby path = args.path if "path" in arg_set else None 79c48d8b04SBranden Bonaby if (path and path[-1] == "/"): 80c48d8b04SBranden Bonaby path = path[:-1] 81c48d8b04SBranden Bonaby validate_args_path(path, arg_set, file_map) 82c48d8b04SBranden Bonaby if (path and "enable_single" in arg_set): 83c48d8b04SBranden Bonaby state_path = locate_state(path, file_map) 84c48d8b04SBranden Bonaby set_test_state(state_path, dev_state.on.value, args.quiet) 85c48d8b04SBranden Bonaby 86c48d8b04SBranden Bonaby # Use subparsers as the key for different actions 87c48d8b04SBranden Bonaby if ("delay" in arg_set): 88c48d8b04SBranden Bonaby validate_delay_values(args.delay_time) 89c48d8b04SBranden Bonaby if (args.enable_all): 90c48d8b04SBranden Bonaby set_delay_all_devices(file_map, args.delay_time, 91c48d8b04SBranden Bonaby args.quiet) 92c48d8b04SBranden Bonaby else: 93c48d8b04SBranden Bonaby set_delay_values(path, file_map, args.delay_time, 94c48d8b04SBranden Bonaby args.quiet) 95c48d8b04SBranden Bonaby elif ("disable_all" in arg_set or "D" in arg_set): 96c48d8b04SBranden Bonaby disable_all_testing(file_map) 97c48d8b04SBranden Bonaby elif ("disable_single" in arg_set or "d" in arg_set): 98c48d8b04SBranden Bonaby disable_testing_single_device(path, file_map) 99c48d8b04SBranden Bonaby elif ("view_all" in arg_set or "V" in arg_set): 100c48d8b04SBranden Bonaby get_all_devices_test_status(file_map) 101c48d8b04SBranden Bonaby elif ("view_single" in arg_set or "v" in arg_set): 102c48d8b04SBranden Bonaby get_device_test_values(path, file_map) 103c48d8b04SBranden Bonaby 104c48d8b04SBranden Bonaby# Get the state location 105c48d8b04SBranden Bonabydef locate_state(device, file_map): 106c48d8b04SBranden Bonaby return file_map[device][f_names.state_f.value] 107c48d8b04SBranden Bonaby 108c48d8b04SBranden Bonaby# Validate delay values to make sure they are acceptable to 109c48d8b04SBranden Bonaby# enable delays on a device 110c48d8b04SBranden Bonabydef validate_delay_values(delay): 111c48d8b04SBranden Bonaby 112c48d8b04SBranden Bonaby if (delay[0] == -1 and delay[1] == -1): 113c48d8b04SBranden Bonaby print("\nError, At least 1 value must be greater than 0") 114c48d8b04SBranden Bonaby exit(-1) 115c48d8b04SBranden Bonaby for i in delay: 116c48d8b04SBranden Bonaby if (i < -1 or i == 0 or i > 1000): 117c48d8b04SBranden Bonaby print("\nError, Values must be equal to -1 " 118c48d8b04SBranden Bonaby "or be > 0 and <= 1000") 119c48d8b04SBranden Bonaby exit(-1) 120c48d8b04SBranden Bonaby 121c48d8b04SBranden Bonaby# Validate argument path 122c48d8b04SBranden Bonabydef validate_args_path(path, arg_set, file_map): 123c48d8b04SBranden Bonaby 124c48d8b04SBranden Bonaby if (not path and any(element in arg_set for element in single_actions)): 125c48d8b04SBranden Bonaby print("Error, path (-p) REQUIRED for the specified option. " 126c48d8b04SBranden Bonaby "Use (-h) to check usage.") 127c48d8b04SBranden Bonaby exit(-1) 128c48d8b04SBranden Bonaby elif (path and any(item in arg_set for item in all_actions)): 129c48d8b04SBranden Bonaby print("Error, path (-p) NOT REQUIRED for the specified option. " 130c48d8b04SBranden Bonaby "Use (-h) to check usage." ) 131c48d8b04SBranden Bonaby exit(-1) 132c48d8b04SBranden Bonaby elif (path not in file_map and any(item in arg_set 133c48d8b04SBranden Bonaby for item in single_actions)): 134c48d8b04SBranden Bonaby print("Error, path '{}' not a valid vmbus device".format(path)) 135c48d8b04SBranden Bonaby exit(-1) 136c48d8b04SBranden Bonaby 137c48d8b04SBranden Bonaby# display Testing status of single device 138c48d8b04SBranden Bonabydef get_device_test_values(path, file_map): 139c48d8b04SBranden Bonaby 140c48d8b04SBranden Bonaby for name in file_map[path]: 141c48d8b04SBranden Bonaby file_location = file_map[path][name] 142c48d8b04SBranden Bonaby print( name + " = " + str(read_test_files(file_location))) 143c48d8b04SBranden Bonaby 144c48d8b04SBranden Bonaby# Create a map of the vmbus devices and their associated files 145c48d8b04SBranden Bonaby# [key=device, value = [key = filename, value = file path]] 146c48d8b04SBranden Bonabydef recursive_file_lookup(path, file_map): 147c48d8b04SBranden Bonaby 148c48d8b04SBranden Bonaby for f_path in glob.iglob(path + '**/*'): 149c48d8b04SBranden Bonaby if (os.path.isfile(f_path)): 150c48d8b04SBranden Bonaby if (f_path.rsplit("/",2)[0] == debugfs_hyperv_path): 151c48d8b04SBranden Bonaby directory = f_path.rsplit("/",1)[0] 152c48d8b04SBranden Bonaby else: 153c48d8b04SBranden Bonaby directory = f_path.rsplit("/",2)[0] 154c48d8b04SBranden Bonaby f_name = f_path.split("/")[-1] 155c48d8b04SBranden Bonaby if (file_map.get(directory)): 156c48d8b04SBranden Bonaby file_map[directory].update({f_name:f_path}) 157c48d8b04SBranden Bonaby else: 158c48d8b04SBranden Bonaby file_map[directory] = {f_name:f_path} 159c48d8b04SBranden Bonaby elif (os.path.isdir(f_path)): 160c48d8b04SBranden Bonaby recursive_file_lookup(f_path,file_map) 161c48d8b04SBranden Bonaby return file_map 162c48d8b04SBranden Bonaby 163c48d8b04SBranden Bonaby# display Testing state of devices 164c48d8b04SBranden Bonabydef get_all_devices_test_status(file_map): 165c48d8b04SBranden Bonaby 166c48d8b04SBranden Bonaby for device in file_map: 167*ed0cf84eSAni Sinha if (get_test_state(locate_state(device, file_map)) == 1): 168c48d8b04SBranden Bonaby print("Testing = ON for: {}" 169c48d8b04SBranden Bonaby .format(device.split("/")[5])) 170c48d8b04SBranden Bonaby else: 171c48d8b04SBranden Bonaby print("Testing = OFF for: {}" 172c48d8b04SBranden Bonaby .format(device.split("/")[5])) 173c48d8b04SBranden Bonaby 174c48d8b04SBranden Bonaby# read the vmbus device files, path must be absolute path before calling 175c48d8b04SBranden Bonabydef read_test_files(path): 176c48d8b04SBranden Bonaby try: 177c48d8b04SBranden Bonaby with open(path,"r") as f: 178c48d8b04SBranden Bonaby file_value = f.readline().strip() 179c48d8b04SBranden Bonaby return int(file_value) 180c48d8b04SBranden Bonaby 181c48d8b04SBranden Bonaby except IOError as e: 182c48d8b04SBranden Bonaby errno, strerror = e.args 183c48d8b04SBranden Bonaby print("I/O error({0}): {1} on file {2}" 184c48d8b04SBranden Bonaby .format(errno, strerror, path)) 185c48d8b04SBranden Bonaby exit(-1) 186c48d8b04SBranden Bonaby except ValueError: 187c48d8b04SBranden Bonaby print ("Element to int conversion error in: \n{}".format(path)) 188c48d8b04SBranden Bonaby exit(-1) 189c48d8b04SBranden Bonaby 190c48d8b04SBranden Bonaby# writing to vmbus device files, path must be absolute path before calling 191c48d8b04SBranden Bonabydef write_test_files(path, value): 192c48d8b04SBranden Bonaby 193c48d8b04SBranden Bonaby try: 194c48d8b04SBranden Bonaby with open(path,"w") as f: 195c48d8b04SBranden Bonaby f.write("{}".format(value)) 196c48d8b04SBranden Bonaby except IOError as e: 197c48d8b04SBranden Bonaby errno, strerror = e.args 198c48d8b04SBranden Bonaby print("I/O error({0}): {1} on file {2}" 199c48d8b04SBranden Bonaby .format(errno, strerror, path)) 200c48d8b04SBranden Bonaby exit(-1) 201c48d8b04SBranden Bonaby 202c48d8b04SBranden Bonaby# set testing state of device 203c48d8b04SBranden Bonabydef set_test_state(state_path, state_value, quiet): 204c48d8b04SBranden Bonaby 205c48d8b04SBranden Bonaby write_test_files(state_path, state_value) 206*ed0cf84eSAni Sinha if (get_test_state(state_path) == 1): 207c48d8b04SBranden Bonaby if (not quiet): 208c48d8b04SBranden Bonaby print("Testing = ON for device: {}" 209c48d8b04SBranden Bonaby .format(state_path.split("/")[5])) 210c48d8b04SBranden Bonaby else: 211c48d8b04SBranden Bonaby if (not quiet): 212c48d8b04SBranden Bonaby print("Testing = OFF for device: {}" 213c48d8b04SBranden Bonaby .format(state_path.split("/")[5])) 214c48d8b04SBranden Bonaby 215c48d8b04SBranden Bonaby# get testing state of device 216c48d8b04SBranden Bonabydef get_test_state(state_path): 217c48d8b04SBranden Bonaby #state == 1 - test = ON 218c48d8b04SBranden Bonaby #state == 0 - test = OFF 219c48d8b04SBranden Bonaby return read_test_files(state_path) 220c48d8b04SBranden Bonaby 221c48d8b04SBranden Bonaby# write 1 - 1000 microseconds, into a single device using the 222c48d8b04SBranden Bonaby# fuzz_test_buffer_interrupt_delay and fuzz_test_message_delay 223c48d8b04SBranden Bonaby# debugfs attributes 224c48d8b04SBranden Bonabydef set_delay_values(device, file_map, delay_length, quiet): 225c48d8b04SBranden Bonaby 226c48d8b04SBranden Bonaby try: 227c48d8b04SBranden Bonaby interrupt = file_map[device][f_names.buff_f.value] 228c48d8b04SBranden Bonaby message = file_map[device][f_names.mess_f.value] 229c48d8b04SBranden Bonaby 230c48d8b04SBranden Bonaby # delay[0]- buffer interrupt delay, delay[1]- message delay 231c48d8b04SBranden Bonaby if (delay_length[0] >= 0 and delay_length[0] <= 1000): 232c48d8b04SBranden Bonaby write_test_files(interrupt, delay_length[0]) 233c48d8b04SBranden Bonaby if (delay_length[1] >= 0 and delay_length[1] <= 1000): 234c48d8b04SBranden Bonaby write_test_files(message, delay_length[1]) 235c48d8b04SBranden Bonaby if (not quiet): 236c48d8b04SBranden Bonaby print("Buffer delay testing = {} for: {}" 237c48d8b04SBranden Bonaby .format(read_test_files(interrupt), 238c48d8b04SBranden Bonaby interrupt.split("/")[5])) 239c48d8b04SBranden Bonaby print("Message delay testing = {} for: {}" 240c48d8b04SBranden Bonaby .format(read_test_files(message), 241c48d8b04SBranden Bonaby message.split("/")[5])) 242c48d8b04SBranden Bonaby except IOError as e: 243c48d8b04SBranden Bonaby errno, strerror = e.args 244c48d8b04SBranden Bonaby print("I/O error({0}): {1} on files {2}{3}" 245c48d8b04SBranden Bonaby .format(errno, strerror, interrupt, message)) 246c48d8b04SBranden Bonaby exit(-1) 247c48d8b04SBranden Bonaby 248c48d8b04SBranden Bonaby# enabling delay testing on all devices 249c48d8b04SBranden Bonabydef set_delay_all_devices(file_map, delay, quiet): 250c48d8b04SBranden Bonaby 251c48d8b04SBranden Bonaby for device in (file_map): 252c48d8b04SBranden Bonaby set_test_state(locate_state(device, file_map), 253c48d8b04SBranden Bonaby dev_state.on.value, 254c48d8b04SBranden Bonaby quiet) 255c48d8b04SBranden Bonaby set_delay_values(device, file_map, delay, quiet) 256c48d8b04SBranden Bonaby 257c48d8b04SBranden Bonaby# disable all testing on a SINGLE device. 258c48d8b04SBranden Bonabydef disable_testing_single_device(device, file_map): 259c48d8b04SBranden Bonaby 260c48d8b04SBranden Bonaby for name in file_map[device]: 261c48d8b04SBranden Bonaby file_location = file_map[device][name] 262c48d8b04SBranden Bonaby write_test_files(file_location, dev_state.off.value) 263c48d8b04SBranden Bonaby print("ALL testing now OFF for {}".format(device.split("/")[-1])) 264c48d8b04SBranden Bonaby 265c48d8b04SBranden Bonaby# disable all testing on ALL devices 266c48d8b04SBranden Bonabydef disable_all_testing(file_map): 267c48d8b04SBranden Bonaby 268c48d8b04SBranden Bonaby for device in file_map: 269c48d8b04SBranden Bonaby disable_testing_single_device(device, file_map) 270c48d8b04SBranden Bonaby 271c48d8b04SBranden Bonabydef parse_args(): 272c48d8b04SBranden Bonaby parser = argparse.ArgumentParser(prog = "vmbus_testing",usage ="\n" 273c48d8b04SBranden Bonaby "%(prog)s [delay] [-h] [-e|-E] -t [-p]\n" 274c48d8b04SBranden Bonaby "%(prog)s [view_all | V] [-h]\n" 275c48d8b04SBranden Bonaby "%(prog)s [disable_all | D] [-h]\n" 276c48d8b04SBranden Bonaby "%(prog)s [disable_single | d] [-h|-p]\n" 277c48d8b04SBranden Bonaby "%(prog)s [view_single | v] [-h|-p]\n" 278c48d8b04SBranden Bonaby "%(prog)s --version\n", 279c48d8b04SBranden Bonaby description = "\nUse lsvmbus to get vmbus device type " 280c48d8b04SBranden Bonaby "information.\n" "\nThe debugfs root path is " 281c48d8b04SBranden Bonaby "/sys/kernel/debug/hyperv", 282c48d8b04SBranden Bonaby formatter_class = RawDescriptionHelpFormatter) 283c48d8b04SBranden Bonaby subparsers = parser.add_subparsers(dest = "action") 284c48d8b04SBranden Bonaby parser.add_argument("--version", action = "version", 285c48d8b04SBranden Bonaby version = '%(prog)s 0.1.0') 286c48d8b04SBranden Bonaby parser.add_argument("-q","--quiet", action = "store_true", 287c48d8b04SBranden Bonaby help = "silence none important test messages." 288c48d8b04SBranden Bonaby " This will only work when enabling testing" 289c48d8b04SBranden Bonaby " on a device.") 290c48d8b04SBranden Bonaby # Use the path parser to hold the --path attribute so it can 291c48d8b04SBranden Bonaby # be shared between subparsers. Also do the same for the state 292c48d8b04SBranden Bonaby # parser, as all testing methods will use --enable_all and 293c48d8b04SBranden Bonaby # enable_single. 294c48d8b04SBranden Bonaby path_parser = argparse.ArgumentParser(add_help=False) 295c48d8b04SBranden Bonaby path_parser.add_argument("-p","--path", metavar = "", 296c48d8b04SBranden Bonaby help = "Debugfs path to a vmbus device. The path " 297c48d8b04SBranden Bonaby "must be the absolute path to the device.") 298c48d8b04SBranden Bonaby state_parser = argparse.ArgumentParser(add_help=False) 299c48d8b04SBranden Bonaby state_group = state_parser.add_mutually_exclusive_group(required = True) 300c48d8b04SBranden Bonaby state_group.add_argument("-E", "--enable_all", action = "store_const", 301c48d8b04SBranden Bonaby const = "enable_all", 302c48d8b04SBranden Bonaby help = "Enable the specified test type " 303c48d8b04SBranden Bonaby "on ALL vmbus devices.") 304c48d8b04SBranden Bonaby state_group.add_argument("-e", "--enable_single", 305c48d8b04SBranden Bonaby action = "store_const", 306c48d8b04SBranden Bonaby const = "enable_single", 307c48d8b04SBranden Bonaby help = "Enable the specified test type on a " 308c48d8b04SBranden Bonaby "SINGLE vmbus device.") 309c48d8b04SBranden Bonaby parser_delay = subparsers.add_parser("delay", 310c48d8b04SBranden Bonaby parents = [state_parser, path_parser], 311c48d8b04SBranden Bonaby help = "Delay the ring buffer interrupt or the " 312c48d8b04SBranden Bonaby "ring buffer message reads in microseconds.", 313c48d8b04SBranden Bonaby prog = "vmbus_testing", 314c48d8b04SBranden Bonaby usage = "%(prog)s [-h]\n" 315c48d8b04SBranden Bonaby "%(prog)s -E -t [value] [value]\n" 316c48d8b04SBranden Bonaby "%(prog)s -e -t [value] [value] -p", 317c48d8b04SBranden Bonaby description = "Delay the ring buffer interrupt for " 318c48d8b04SBranden Bonaby "vmbus devices, or delay the ring buffer message " 319c48d8b04SBranden Bonaby "reads for vmbus devices (both in microseconds). This " 320c48d8b04SBranden Bonaby "is only on the host to guest channel.") 321c48d8b04SBranden Bonaby parser_delay.add_argument("-t", "--delay_time", metavar = "", nargs = 2, 322c48d8b04SBranden Bonaby type = check_range, default =[0,0], required = (True), 323c48d8b04SBranden Bonaby help = "Set [buffer] & [message] delay time. " 324c48d8b04SBranden Bonaby "Value constraints: -1 == value " 325c48d8b04SBranden Bonaby "or 0 < value <= 1000.\n" 326c48d8b04SBranden Bonaby "Use -1 to keep the previous value for that delay " 327c48d8b04SBranden Bonaby "type, or a value > 0 <= 1000 to change the delay " 328c48d8b04SBranden Bonaby "time.") 329c48d8b04SBranden Bonaby parser_dis_all = subparsers.add_parser("disable_all", 330c48d8b04SBranden Bonaby aliases = ['D'], prog = "vmbus_testing", 331c48d8b04SBranden Bonaby usage = "%(prog)s [disable_all | D] -h\n" 332c48d8b04SBranden Bonaby "%(prog)s [disable_all | D]\n", 333c48d8b04SBranden Bonaby help = "Disable ALL testing on ALL vmbus devices.", 334c48d8b04SBranden Bonaby description = "Disable ALL testing on ALL vmbus " 335c48d8b04SBranden Bonaby "devices.") 336c48d8b04SBranden Bonaby parser_dis_single = subparsers.add_parser("disable_single", 337c48d8b04SBranden Bonaby aliases = ['d'], 338c48d8b04SBranden Bonaby parents = [path_parser], prog = "vmbus_testing", 339c48d8b04SBranden Bonaby usage = "%(prog)s [disable_single | d] -h\n" 340c48d8b04SBranden Bonaby "%(prog)s [disable_single | d] -p\n", 341c48d8b04SBranden Bonaby help = "Disable ALL testing on a SINGLE vmbus device.", 342c48d8b04SBranden Bonaby description = "Disable ALL testing on a SINGLE vmbus " 343c48d8b04SBranden Bonaby "device.") 344c48d8b04SBranden Bonaby parser_view_all = subparsers.add_parser("view_all", aliases = ['V'], 345c48d8b04SBranden Bonaby help = "View the test state for ALL vmbus devices.", 346c48d8b04SBranden Bonaby prog = "vmbus_testing", 347c48d8b04SBranden Bonaby usage = "%(prog)s [view_all | V] -h\n" 348c48d8b04SBranden Bonaby "%(prog)s [view_all | V]\n", 349c48d8b04SBranden Bonaby description = "This shows the test state for ALL the " 350c48d8b04SBranden Bonaby "vmbus devices.") 351c48d8b04SBranden Bonaby parser_view_single = subparsers.add_parser("view_single", 352c48d8b04SBranden Bonaby aliases = ['v'],parents = [path_parser], 353c48d8b04SBranden Bonaby help = "View the test values for a SINGLE vmbus " 354c48d8b04SBranden Bonaby "device.", 355c48d8b04SBranden Bonaby description = "This shows the test values for a SINGLE " 356c48d8b04SBranden Bonaby "vmbus device.", prog = "vmbus_testing", 357c48d8b04SBranden Bonaby usage = "%(prog)s [view_single | v] -h\n" 358c48d8b04SBranden Bonaby "%(prog)s [view_single | v] -p") 359c48d8b04SBranden Bonaby 360c48d8b04SBranden Bonaby return parser.parse_args() 361c48d8b04SBranden Bonaby 362c48d8b04SBranden Bonaby# value checking for range checking input in parser 363c48d8b04SBranden Bonabydef check_range(arg1): 364c48d8b04SBranden Bonaby 365c48d8b04SBranden Bonaby try: 366c48d8b04SBranden Bonaby val = int(arg1) 367c48d8b04SBranden Bonaby except ValueError as err: 368c48d8b04SBranden Bonaby raise argparse.ArgumentTypeError(str(err)) 369c48d8b04SBranden Bonaby if val < -1 or val > 1000: 370c48d8b04SBranden Bonaby message = ("\n\nvalue must be -1 or 0 < value <= 1000. " 371c48d8b04SBranden Bonaby "Value program received: {}\n").format(val) 372c48d8b04SBranden Bonaby raise argparse.ArgumentTypeError(message) 373c48d8b04SBranden Bonaby return val 374c48d8b04SBranden Bonaby 375c48d8b04SBranden Bonabyif __name__ == "__main__": 376c48d8b04SBranden Bonaby main() 377