xref: /kernel/linux/linux-5.10/tools/hv/vmbus_testing (revision 8c2ecf20)
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