| George Keishing | e7e9171 | 2021-09-03 11:28:44 -0500 | [diff] [blame] | 1 | #!/usr/bin/env python3 | 
| Michael Walsh | 19621ba | 2018-12-03 17:16:02 -0600 | [diff] [blame] | 2 |  | 
 | 3 | r""" | 
 | 4 | A python companion file for ipmi_client.robot. | 
 | 5 | """ | 
 | 6 |  | 
| Michael Walsh | 355197a | 2019-01-21 15:06:10 -0600 | [diff] [blame] | 7 | import collections | 
| Michael Walsh | 19621ba | 2018-12-03 17:16:02 -0600 | [diff] [blame] | 8 | import gen_print as gp | 
 | 9 | import gen_cmd as gc | 
 | 10 | from robot.libraries.BuiltIn import BuiltIn | 
 | 11 |  | 
 | 12 |  | 
| Michael Walsh | 355197a | 2019-01-21 15:06:10 -0600 | [diff] [blame] | 13 | # Set default values for required IPMI options. | 
 | 14 | ipmi_interface = 'lanplus' | 
| Rahul Maheshwari | 3aeae4e | 2020-04-03 07:45:50 -0500 | [diff] [blame] | 15 | ipmi_cipher_suite = BuiltIn().get_variable_value("${IPMI_CIPHER_LEVEL}", '17') | 
| George Keishing | 75f55dc | 2021-03-29 10:48:09 -0500 | [diff] [blame] | 16 | ipmi_timeout = BuiltIn().get_variable_value("${IPMI_TIMEOUT}", '3') | 
| George Keishing | e33ad1d | 2019-12-09 11:17:36 -0600 | [diff] [blame] | 17 | ipmi_port = BuiltIn().get_variable_value("${IPMI_PORT}", '623') | 
| Michael Walsh | 355197a | 2019-01-21 15:06:10 -0600 | [diff] [blame] | 18 | ipmi_username = BuiltIn().get_variable_value("${IPMI_USERNAME}", "root") | 
 | 19 | ipmi_password = BuiltIn().get_variable_value("${IPMI_PASSWORD}", "0penBmc") | 
 | 20 | ipmi_host = BuiltIn().get_variable_value("${OPENBMC_HOST}") | 
 | 21 |  | 
 | 22 | # Create a list of the required IPMI options. | 
| George Keishing | 75f55dc | 2021-03-29 10:48:09 -0500 | [diff] [blame] | 23 | ipmi_required_options = ['I', 'C', 'N', 'p', 'U', 'P', 'H'] | 
| Michael Walsh | 355197a | 2019-01-21 15:06:10 -0600 | [diff] [blame] | 24 | # The following dictionary maps the ipmitool option names (e.g. "I") to our | 
 | 25 | # more descriptive names (e.g. "interface") for the required options. | 
 | 26 | ipmi_option_name_map = { | 
 | 27 |     'I': 'interface', | 
 | 28 |     'C': 'cipher_suite', | 
| George Keishing | 75f55dc | 2021-03-29 10:48:09 -0500 | [diff] [blame] | 29 |     'N': 'timeout', | 
| George Keishing | e33ad1d | 2019-12-09 11:17:36 -0600 | [diff] [blame] | 30 |     'p': 'port', | 
| Michael Walsh | 355197a | 2019-01-21 15:06:10 -0600 | [diff] [blame] | 31 |     'U': 'username', | 
 | 32 |     'P': 'password', | 
 | 33 |     'H': 'host', | 
 | 34 | } | 
 | 35 |  | 
 | 36 |  | 
 | 37 | def create_ipmi_ext_command_string(command, **options): | 
| Michael Walsh | 19621ba | 2018-12-03 17:16:02 -0600 | [diff] [blame] | 38 |     r""" | 
| Michael Walsh | 355197a | 2019-01-21 15:06:10 -0600 | [diff] [blame] | 39 |     Create and return an IPMI external command string which is fit to be run | 
 | 40 |     from a bash command line. | 
| Michael Walsh | 19621ba | 2018-12-03 17:16:02 -0600 | [diff] [blame] | 41 |  | 
| Michael Walsh | 355197a | 2019-01-21 15:06:10 -0600 | [diff] [blame] | 42 |     Example: | 
| George Keishing | f402765 | 2019-01-10 23:58:29 -0600 | [diff] [blame] | 43 |  | 
| Michael Walsh | 355197a | 2019-01-21 15:06:10 -0600 | [diff] [blame] | 44 |     ipmi_ext_cmd = create_ipmi_ext_command_string('power status') | 
| Michael Walsh | 19621ba | 2018-12-03 17:16:02 -0600 | [diff] [blame] | 45 |  | 
| Michael Walsh | 355197a | 2019-01-21 15:06:10 -0600 | [diff] [blame] | 46 |     Result: | 
| George Keishing | e33ad1d | 2019-12-09 11:17:36 -0600 | [diff] [blame] | 47 |     ipmitool -I lanplus -C 3 -p 623 -P ******** -H x.x.x.x power status | 
| Michael Walsh | 19621ba | 2018-12-03 17:16:02 -0600 | [diff] [blame] | 48 |  | 
| Michael Walsh | 355197a | 2019-01-21 15:06:10 -0600 | [diff] [blame] | 49 |     Example: | 
 | 50 |  | 
 | 51 |     ipmi_ext_cmd = create_ipmi_ext_command_string('power status', C='4') | 
 | 52 |  | 
 | 53 |     Result: | 
| George Keishing | e33ad1d | 2019-12-09 11:17:36 -0600 | [diff] [blame] | 54 |     ipmitool -I lanplus -C 4 -p 623 -P ******** -H x.x.x.x power status | 
| Michael Walsh | 19621ba | 2018-12-03 17:16:02 -0600 | [diff] [blame] | 55 |  | 
 | 56 |     Description of argument(s): | 
| Michael Walsh | 355197a | 2019-01-21 15:06:10 -0600 | [diff] [blame] | 57 |     command                         The ipmitool command (e.g. 'power status'). | 
 | 58 |     options                         Any desired options that are understood by | 
 | 59 |                                     ipmitool (see iptmitool's help text for a | 
 | 60 |                                     complete list).  If the caller does NOT | 
 | 61 |                                     provide any of several required options | 
 | 62 |                                     (e.g. "P", i.e. password), this function | 
 | 63 |                                     will include them on the caller's behalf | 
 | 64 |                                     using default values. | 
| Michael Walsh | 19621ba | 2018-12-03 17:16:02 -0600 | [diff] [blame] | 65 |     """ | 
 | 66 |  | 
| Michael Walsh | 355197a | 2019-01-21 15:06:10 -0600 | [diff] [blame] | 67 |     new_options = collections.OrderedDict() | 
 | 68 |     for option in ipmi_required_options: | 
| George Keishing | 2b32c10 | 2021-03-29 14:59:00 -0500 | [diff] [blame] | 69 |         # This is to prevent boot table "-N 10" vs user input timeout. | 
 | 70 |         if " -N " in command and option == "N": | 
 | 71 |             continue | 
| Michael Walsh | 355197a | 2019-01-21 15:06:10 -0600 | [diff] [blame] | 72 |         if option in options: | 
 | 73 |             # If the caller has specified this particular option, use it in | 
 | 74 |             # preference to the default value. | 
 | 75 |             new_options[option] = options[option] | 
 | 76 |             # Delete the value from the caller's options. | 
 | 77 |             del options[option] | 
 | 78 |         else: | 
 | 79 |             # The caller hasn't specified this required option so specify it | 
 | 80 |             # for them using the global value. | 
 | 81 |             var_name = 'ipmi_' + ipmi_option_name_map[option] | 
 | 82 |             value = eval(var_name) | 
 | 83 |             new_options[option] = value | 
 | 84 |     # Include the remainder of the caller's options in the new options | 
 | 85 |     # dictionary. | 
 | 86 |     for key, value in options.items(): | 
 | 87 |         new_options[key] = value | 
| Michael Walsh | 19621ba | 2018-12-03 17:16:02 -0600 | [diff] [blame] | 88 |  | 
| Michael Walsh | 355197a | 2019-01-21 15:06:10 -0600 | [diff] [blame] | 89 |     return gc.create_command_string('ipmitool', command, new_options) | 
| Michael Walsh | 19621ba | 2018-12-03 17:16:02 -0600 | [diff] [blame] | 90 |  | 
| Michael Walsh | 355197a | 2019-01-21 15:06:10 -0600 | [diff] [blame] | 91 |  | 
 | 92 | def verify_ipmi_user_parm_accepted(): | 
 | 93 |     r""" | 
 | 94 |     Deterimine whether the OBMC accepts the '-U' ipmitool option and adjust | 
 | 95 |     the global ipmi_required_options accordingly. | 
 | 96 |     """ | 
 | 97 |  | 
 | 98 |     # Assumption: "U" is in the global ipmi_required_options. | 
 | 99 |     global ipmi_required_options | 
| Michael Walsh | 19621ba | 2018-12-03 17:16:02 -0600 | [diff] [blame] | 100 |     print_output = 0 | 
| Michael Walsh | 355197a | 2019-01-21 15:06:10 -0600 | [diff] [blame] | 101 |  | 
 | 102 |     command_string = create_ipmi_ext_command_string('power status') | 
 | 103 |     rc, stdout = gc.shell_cmd(command_string, | 
 | 104 |                               print_output=print_output, | 
 | 105 |                               show_err=0, | 
 | 106 |                               ignore_err=1) | 
 | 107 |     gp.qprint_var(rc, 1) | 
 | 108 |     if rc == 0: | 
 | 109 |         # The OBMC accepts the ipmitool "-U" option so new further work needs | 
 | 110 |         # to be done. | 
| Michael Walsh | 19621ba | 2018-12-03 17:16:02 -0600 | [diff] [blame] | 111 |         return | 
 | 112 |  | 
| Michael Walsh | 355197a | 2019-01-21 15:06:10 -0600 | [diff] [blame] | 113 |     # Remove the "U" option from ipmi_required_options to allow us to create a | 
 | 114 |     # command string without the "U" option. | 
 | 115 |     if 'U' in ipmi_required_options: | 
 | 116 |         del ipmi_required_options[ipmi_required_options.index('U')] | 
 | 117 |     command_string = create_ipmi_ext_command_string('power status') | 
 | 118 |     rc, stdout = gc.shell_cmd(command_string, | 
 | 119 |                               print_output=print_output, | 
 | 120 |                               show_err=0, | 
 | 121 |                               ignore_err=1) | 
 | 122 |     gp.qprint_var(rc, 1) | 
 | 123 |     if rc == 0: | 
 | 124 |         # The "U" option has been removed from the ipmi_required_options | 
 | 125 |         # global variable. | 
| Michael Walsh | 19621ba | 2018-12-03 17:16:02 -0600 | [diff] [blame] | 126 |         return | 
 | 127 |  | 
| Michael Walsh | 355197a | 2019-01-21 15:06:10 -0600 | [diff] [blame] | 128 |     message = "Unable to run ipmitool (with or without the '-U' option).\n" | 
 | 129 |     gp.print_error(message) | 
 | 130 |  | 
 | 131 |     # Revert to original ipmi_required_options by inserting 'U' right before | 
 | 132 |     # 'P'. | 
 | 133 |     ipmi_required_options.insert(ipmi_required_options.index('P'), 'U') | 
| Michael Walsh | 19621ba | 2018-12-03 17:16:02 -0600 | [diff] [blame] | 134 |  | 
 | 135 |  | 
| Michael Walsh | 355197a | 2019-01-21 15:06:10 -0600 | [diff] [blame] | 136 | def ipmi_setup(): | 
 | 137 |     r""" | 
 | 138 |     Perform all required setup for running iptmitool commands. | 
 | 139 |     """ | 
 | 140 |  | 
 | 141 |     verify_ipmi_user_parm_accepted() | 
 | 142 |  | 
 | 143 |  | 
 | 144 | ipmi_setup() | 
 | 145 |  | 
 | 146 |  | 
 | 147 | def process_ipmi_user_options(command): | 
 | 148 |     r""" | 
 | 149 |     Return the buffer with any ipmi_user_options pre-pended. | 
 | 150 |  | 
 | 151 |     Description of argument(s): | 
 | 152 |     command                         An IPMI command (e.g. "power status"). | 
 | 153 |     """ | 
 | 154 |  | 
 | 155 |     ipmi_user_options = BuiltIn().get_variable_value("${IPMI_USER_OPTIONS}", '') | 
 | 156 |     if ipmi_user_options == "": | 
 | 157 |         return command | 
 | 158 |     return ipmi_user_options + " " + command |