1#!/usr/bin/env python3 2 3import os 4import sys 5 6from robot.libraries.BuiltIn import BuiltIn as robotBuildIn 7 8sys.path.append(__file__.split(__file__.split("/")[-1])[0] + "../ffdc") 9from ffdc_collector import ffdc_collector # NOQA 10from ssh_utility import SSHRemoteclient # NOQA 11 12# (Sub) String constants used for input dictionary key search 13HOST = "HOST" 14USER = "USERNAME" 15PASSWD = "PASSWORD" 16PORT_SSH = "SSH_PORT" 17PORT_HTTPS = "HTTPS_PORT" 18PORT_IPMI = "IPMI_PORT" 19CONFIG = "CONFIG" 20TYPE = "TYPE" 21LOC = "LOCATION" 22PROTOCOL = "PROTOCOL" 23ENV_VARS = "ENV_VARS" 24ECONFIG = "ECONFIG" 25LOGLEVEL = "LOG" 26 27 28def ffdc_robot_script_cli(**kwargs): 29 r""" 30 31 For the specified host, this method provide automation testcases the interface to 32 the new ffdc collector ../ffdc/ffdc_collector.py via robot variable FFDC_DEFAULT 33 34 variable FFDC_DEFAULT:1, by default use the existing ffdc collection method. 35 variable FFDC_DEFAULT:0 use the new ffdc method 36 37 Command examples: 38 (1) Legacy ffdc collection 39 python3 -m robot -v OPENBMC_HOST:<> -v OPENBMC_USERNAME:<> \ 40 -v OPENBMC_PASSWORD:<> ./tools/myffdc.robot 41 (2) New ffdc collection 42 python3 -m robot -v OPENBMC_HOST:<> -v OPENBMC_USERNAME:<> \ 43 -v OPENBMC_PASSWORD:<> -v FFDC_DEFAULT:0 ./tools/myffdc.robot 44 45 Description of argument(s)in dictionary: xx can be anything appropriate 46 47 xx_HOST:hostname name/ip of the targeted (remote) system 48 xx_USERNAME:username user on the targeted system with access to FFDC files 49 xx_PASSWORD:password password for user on targeted system 50 xx_CONFIG:ffdc_config configuration file listing commands and files for FFDC 51 xx_LOCATION:location where to store collected FFDC. Default: <current dir>/logs/ 52 xx_TYPE:remote_type os type of the remote host. 53 xx_PROTOCOL:remote_protocol Protocol to use to collect data. Default: 'ALL' 54 ENV_VAR:env_vars User define CLI env vars '{"key : "value"}'. Default: "" 55 ECONFIG:econfig User define env vars YAML file. Default: "" 56 LOG_LEVEL:log_level CRITICAL, ERROR, WARNING, INFO, DEBUG. Default: INFO 57 58 Code examples: 59 (1) openbmc_ffdc.robot activate this method with no parm 60 Run Keyword If ${FFDC_DEFAULT} == ${1} FFDC 61 ... ELSE ffdc_robot_script_cli 62 63 (2) Method invocation with parms 64 ffdc_from = {'OS_HOST' : 'os host name or ip', 65 'OS_USERNAME' : 'os username', 66 'OS_PASSWORD' : 'password for os_username', 67 'OS_TYPE' : 'os_type, ubuntu, rhel, aix, etc', 68 } 69 ffdc_robot_script_cli(ffdc_from) 70 71 """ 72 73 robotBuildIn().log_to_console("Collecting FFDC - CLI log collector script") 74 75 if not kwargs: 76 dict_of_parms = {} 77 # When method is invoked with no parm, 78 # use robot variables 79 # OPENBMC_HOST, OPENBMC_USERNAME, OPENBMC_PASSWORD, OPENBMC (type) 80 dict_of_parms["OPENBMC_HOST"] = robotBuildIn().get_variable_value( 81 "${OPENBMC_HOST}", default=None 82 ) 83 dict_of_parms["OPENBMC_USERNAME"] = robotBuildIn().get_variable_value( 84 "${OPENBMC_USERNAME}", default=None 85 ) 86 dict_of_parms["OPENBMC_PASSWORD"] = robotBuildIn().get_variable_value( 87 "${OPENBMC_PASSWORD}", default=None 88 ) 89 dict_of_parms["SSH_PORT"] = robotBuildIn().get_variable_value( 90 "${SSH_PORT}", default=22 91 ) 92 dict_of_parms["HTTPS_PORT"] = robotBuildIn().get_variable_value( 93 "${HTTPS_PORT}", default=443 94 ) 95 dict_of_parms["IPMI_PORT"] = robotBuildIn().get_variable_value( 96 "${IPMI_PORT}", default=623 97 ) 98 dict_of_parms["REMOTE_TYPE"] = "OPENBMC" 99 100 run_ffdc_collector(dict_of_parms) 101 102 else: 103 if isinstance(kwargs, dict): 104 # When method is invoked with user defined dictionary, 105 # dictionary keys has the following format 106 # xx_HOST; xx_USERNAME, xx_PASSWORD, xx_TYPE 107 # where xx is one of OPENBMC, OS, or os_type LINUX/UBUNTU/AIX 108 run_ffdc_collector(**kwargs) 109 110 111def run_ffdc_collector(dict_of_parm): 112 r""" 113 114 Process input parameters and collect information 115 116 Description of argument(s)in dictionary: xx can be anything appropriate 117 118 xx_HOST:hostname name/ip of the targeted (remote) system 119 xx_USERNAME:username user on the targeted system with access to FFDC files 120 xx_PASSWORD:password password for user on targeted system 121 xx_CONFIG:ffdc_config configuration file listing commands and files for FFDC 122 xx_LOCATION:location where to store collected FFDC. Default: <current dir>/logs/ 123 xx_TYPE:remote_type os type of the remote host. 124 xx_PROTOCOL:remote_protocol Protocol to use to collect data. Default: 'ALL' 125 ENV_VAR:env_vars User define CLI env vars '{"key : "value"}'. Default: "" 126 ECONFIG:econfig User define env vars YAML file. Default: "" 127 LOG_LEVEL:log_level CRITICAL, ERROR, WARNING, INFO, DEBUG. Default: INFO 128 129 """ 130 131 # Clear local variables 132 remote = None 133 username = None 134 password = None 135 config = None 136 location = None 137 remote_type = None 138 protocol = None 139 env_vars = None 140 econfig = None 141 log_level = None 142 143 # Process input key/value pairs 144 for key in dict_of_parm.keys(): 145 if HOST in key: 146 remote = dict_of_parm[key] 147 elif USER in key: 148 username = dict_of_parm[key] 149 elif PASSWD in key: 150 password = dict_of_parm[key] 151 elif PORT_SSH in key: 152 port_ssh = dict_of_parm[key] 153 elif PORT_HTTPS in key: 154 port_https = dict_of_parm[key] 155 elif PORT_IPMI in key: 156 port_ipmi = dict_of_parm[key] 157 elif CONFIG in key: 158 config = dict_of_parm[key] 159 elif LOC in key: 160 location = dict_of_parm[key] 161 elif TYPE in key: 162 remote_type = dict_of_parm[key] 163 elif PROTOCOL in key: 164 protocol = dict_of_parm[key] 165 elif ENV_VARS in key: 166 env_vars = dict_of_parm[key] 167 elif ECONFIG in key: 168 econfig = dict_of_parm[key] 169 elif LOGLEVEL in key: 170 log_level = dict_of_parm[key] 171 172 # Set defaults values for parms 173 # that are not specified with input and have acceptable defaults. 174 if not location: 175 # Default FFDC store location 176 location = ( 177 robotBuildIn().get_variable_value("${EXECDIR}", default=None) 178 + "/logs" 179 ) 180 ffdc_collector.validate_local_store(location) 181 182 if not config: 183 # Default FFDC configuration 184 script_path = os.path.dirname(os.path.abspath(__file__)) 185 config = script_path + "/../ffdc/ffdc_config.yaml" 186 187 if not protocol: 188 protocol = "ALL" 189 190 if not env_vars: 191 env_vars = "" 192 193 if not econfig: 194 econfig = "" 195 196 if not log_level: 197 log_level = "INFO" 198 199 # If minimum required inputs are met, go collect. 200 if remote and username and password and remote_type: 201 # Execute data collection 202 this_ffdc = ffdc_collector( 203 remote, 204 username, 205 password, 206 port_ssh, 207 port_https, 208 port_ipmi, 209 config, 210 location, 211 remote_type, 212 protocol, 213 env_vars, 214 econfig, 215 log_level, 216 ) 217 this_ffdc.collect_ffdc() 218 219 # If original ffdc request is for BMC, 220 # attempt to also collect ffdc for HOST_OS if possible. 221 if remote_type.upper() == "OPENBMC": 222 os_host = robotBuildIn().get_variable_value( 223 "${OS_HOST}", default=None 224 ) 225 os_username = robotBuildIn().get_variable_value( 226 "${OS_USERNAME}", default=None 227 ) 228 os_password = robotBuildIn().get_variable_value( 229 "${OS_PASSWORD}", default=None 230 ) 231 232 if os_host and os_username and os_password: 233 os_type = get_os_type(os_host, os_username, os_password) 234 if os_type: 235 os_ffdc = ffdc_collector( 236 os_host, 237 os_username, 238 os_password, 239 config, 240 location, 241 os_type, 242 protocol, 243 env_vars, 244 econfig, 245 log_level, 246 ) 247 os_ffdc.collect_ffdc() 248 249 250def get_os_type(os_host, os_username, os_password): 251 os_type = None 252 253 # If HOST_OS is pingable 254 if os.system("ping -c 1 " + os_host) == 0: 255 r""" 256 Open a ssh connection to targeted system. 257 """ 258 ssh_remoteclient = SSHRemoteclient(os_host, os_username, os_password) 259 260 if ssh_remoteclient.ssh_remoteclient_login(): 261 # Find OS_TYPE 262 cmd_exit_code, err, response = ssh_remoteclient.execute_command( 263 "uname" 264 ) 265 os_type = response.strip() 266 267 # If HOST_OS is linux, expands os_type to one of 268 # the 2 linux distros that have more details in ffdc_config.yaml 269 if os_type.upper() == "LINUX": 270 ( 271 cmd_exit_code, 272 err, 273 response, 274 ) = ssh_remoteclient.execute_command("cat /etc/os-release") 275 linux_distro = response 276 if "redhat" in linux_distro: 277 os_type = "RHEL" 278 elif "ubuntu" in linux_distro: 279 os_type = "UBUNTU" 280 281 if ssh_remoteclient: 282 ssh_remoteclient.ssh_remoteclient_disconnect() 283 284 return os_type 285