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