| #!/usr/bin/env python3 |
| |
| import os |
| import sys |
| |
| from robot.libraries.BuiltIn import BuiltIn as robotBuildIn |
| |
| sys.path.append(__file__.split(__file__.split("/")[-1])[0] + "../ffdc") |
| from ffdc_collector import ffdc_collector # NOQA |
| from ssh_utility import SSHRemoteclient # NOQA |
| |
| # (Sub) String constants used for input dictionary key search |
| HOST = "HOST" |
| USER = "USERNAME" |
| PASSWD = "PASSWORD" |
| PORT_SSH = "SSH_PORT" |
| PORT_HTTPS = "HTTPS_PORT" |
| PORT_IPMI = "IPMI_PORT" |
| CONFIG = "CONFIG" |
| TYPE = "TYPE" |
| LOC = "LOCATION" |
| PROTOCOL = "PROTOCOL" |
| ENV_VARS = "ENV_VARS" |
| ECONFIG = "ECONFIG" |
| LOGLEVEL = "LOG" |
| |
| |
| def ffdc_robot_script_cli(**kwargs): |
| r""" |
| |
| For the specified host, this method provide automation testcases the interface to |
| the new ffdc collector ../ffdc/ffdc_collector.py via robot variable FFDC_DEFAULT |
| |
| variable FFDC_DEFAULT:1, by default use the existing ffdc collection method. |
| variable FFDC_DEFAULT:0 use the new ffdc method |
| |
| Command examples: |
| (1) Legacy ffdc collection |
| python3 -m robot -v OPENBMC_HOST:<> -v OPENBMC_USERNAME:<> \ |
| -v OPENBMC_PASSWORD:<> ./tools/myffdc.robot |
| (2) New ffdc collection |
| python3 -m robot -v OPENBMC_HOST:<> -v OPENBMC_USERNAME:<> \ |
| -v OPENBMC_PASSWORD:<> -v FFDC_DEFAULT:0 ./tools/myffdc.robot |
| |
| Description of argument(s)in dictionary: xx can be anything appropriate |
| |
| xx_HOST:hostname name/ip of the targeted (remote) system |
| xx_USERNAME:username user on the targeted system with access to FFDC files |
| xx_PASSWORD:password password for user on targeted system |
| xx_CONFIG:ffdc_config configuration file listing commands and files for FFDC |
| xx_LOCATION:location where to store collected FFDC. Default: <current dir>/logs/ |
| xx_TYPE:remote_type os type of the remote host. |
| xx_PROTOCOL:remote_protocol Protocol to use to collect data. Default: 'ALL' |
| ENV_VAR:env_vars User define CLI env vars '{"key : "value"}'. Default: "" |
| ECONFIG:econfig User define env vars YAML file. Default: "" |
| LOG_LEVEL:log_level CRITICAL, ERROR, WARNING, INFO, DEBUG. Default: INFO |
| |
| Code examples: |
| (1) openbmc_ffdc.robot activate this method with no parm |
| Run Keyword If ${FFDC_DEFAULT} == ${1} FFDC |
| ... ELSE ffdc_robot_script_cli |
| |
| (2) Method invocation with parms |
| ffdc_from = {'OS_HOST' : 'os host name or ip', |
| 'OS_USERNAME' : 'os username', |
| 'OS_PASSWORD' : 'password for os_username', |
| 'OS_TYPE' : 'os_type, ubuntu, rhel, aix, etc', |
| } |
| ffdc_robot_script_cli(ffdc_from) |
| |
| """ |
| |
| robotBuildIn().log_to_console("Collecting FFDC - CLI log collector script") |
| |
| if not kwargs: |
| dict_of_parms = {} |
| # When method is invoked with no parm, |
| # use robot variables |
| # OPENBMC_HOST, OPENBMC_USERNAME, OPENBMC_PASSWORD, OPENBMC (type) |
| dict_of_parms["OPENBMC_HOST"] = robotBuildIn().get_variable_value( |
| "${OPENBMC_HOST}", default=None |
| ) |
| dict_of_parms["OPENBMC_USERNAME"] = robotBuildIn().get_variable_value( |
| "${OPENBMC_USERNAME}", default=None |
| ) |
| dict_of_parms["OPENBMC_PASSWORD"] = robotBuildIn().get_variable_value( |
| "${OPENBMC_PASSWORD}", default=None |
| ) |
| dict_of_parms["SSH_PORT"] = robotBuildIn().get_variable_value( |
| "${SSH_PORT}", default=22 |
| ) |
| dict_of_parms["HTTPS_PORT"] = robotBuildIn().get_variable_value( |
| "${HTTPS_PORT}", default=443 |
| ) |
| dict_of_parms["IPMI_PORT"] = robotBuildIn().get_variable_value( |
| "${IPMI_PORT}", default=623 |
| ) |
| dict_of_parms["REMOTE_TYPE"] = "OPENBMC" |
| |
| run_ffdc_collector(dict_of_parms) |
| |
| else: |
| if isinstance(kwargs, dict): |
| # When method is invoked with user defined dictionary, |
| # dictionary keys has the following format |
| # xx_HOST; xx_USERNAME, xx_PASSWORD, xx_TYPE |
| # where xx is one of OPENBMC, OS, or os_type LINUX/UBUNTU/AIX |
| run_ffdc_collector(**kwargs) |
| |
| |
| def run_ffdc_collector(dict_of_parm): |
| r""" |
| |
| Process input parameters and collect information |
| |
| Description of argument(s)in dictionary: xx can be anything appropriate |
| |
| xx_HOST:hostname name/ip of the targeted (remote) system |
| xx_USERNAME:username user on the targeted system with access to FFDC files |
| xx_PASSWORD:password password for user on targeted system |
| xx_CONFIG:ffdc_config configuration file listing commands and files for FFDC |
| xx_LOCATION:location where to store collected FFDC. Default: <current dir>/logs/ |
| xx_TYPE:remote_type os type of the remote host. |
| xx_PROTOCOL:remote_protocol Protocol to use to collect data. Default: 'ALL' |
| ENV_VAR:env_vars User define CLI env vars '{"key : "value"}'. Default: "" |
| ECONFIG:econfig User define env vars YAML file. Default: "" |
| LOG_LEVEL:log_level CRITICAL, ERROR, WARNING, INFO, DEBUG. Default: INFO |
| |
| """ |
| |
| # Clear local variables |
| remote = None |
| username = None |
| password = None |
| config = None |
| location = None |
| remote_type = None |
| protocol = None |
| env_vars = None |
| econfig = None |
| log_level = None |
| |
| # Process input key/value pairs |
| for key in dict_of_parm.keys(): |
| if HOST in key: |
| remote = dict_of_parm[key] |
| elif USER in key: |
| username = dict_of_parm[key] |
| elif PASSWD in key: |
| password = dict_of_parm[key] |
| elif PORT_SSH in key: |
| port_ssh = dict_of_parm[key] |
| elif PORT_HTTPS in key: |
| port_https = dict_of_parm[key] |
| elif PORT_IPMI in key: |
| port_ipmi = dict_of_parm[key] |
| elif CONFIG in key: |
| config = dict_of_parm[key] |
| elif LOC in key: |
| location = dict_of_parm[key] |
| elif TYPE in key: |
| remote_type = dict_of_parm[key] |
| elif PROTOCOL in key: |
| protocol = dict_of_parm[key] |
| elif ENV_VARS in key: |
| env_vars = dict_of_parm[key] |
| elif ECONFIG in key: |
| econfig = dict_of_parm[key] |
| elif LOGLEVEL in key: |
| log_level = dict_of_parm[key] |
| |
| # Set defaults values for parms |
| # that are not specified with input and have acceptable defaults. |
| if not location: |
| # Default FFDC store location |
| location = ( |
| robotBuildIn().get_variable_value("${EXECDIR}", default=None) |
| + "/logs" |
| ) |
| ffdc_collector.validate_local_store(location) |
| |
| if not config: |
| # Default FFDC configuration |
| script_path = os.path.dirname(os.path.abspath(__file__)) |
| config = script_path + "/../ffdc/ffdc_config.yaml" |
| |
| if not protocol: |
| protocol = "ALL" |
| |
| if not env_vars: |
| env_vars = "" |
| |
| if not econfig: |
| econfig = "" |
| |
| if not log_level: |
| log_level = "INFO" |
| |
| # If minimum required inputs are met, go collect. |
| if remote and username and password and remote_type: |
| # Execute data collection |
| this_ffdc = ffdc_collector( |
| remote, |
| username, |
| password, |
| port_ssh, |
| port_https, |
| port_ipmi, |
| config, |
| location, |
| remote_type, |
| protocol, |
| env_vars, |
| econfig, |
| log_level, |
| ) |
| this_ffdc.collect_ffdc() |
| |
| # If original ffdc request is for BMC, |
| # attempt to also collect ffdc for HOST_OS if possible. |
| if remote_type.upper() == "OPENBMC": |
| os_host = robotBuildIn().get_variable_value( |
| "${OS_HOST}", default=None |
| ) |
| os_username = robotBuildIn().get_variable_value( |
| "${OS_USERNAME}", default=None |
| ) |
| os_password = robotBuildIn().get_variable_value( |
| "${OS_PASSWORD}", default=None |
| ) |
| |
| if os_host and os_username and os_password: |
| os_type = get_os_type(os_host, os_username, os_password) |
| if os_type: |
| os_ffdc = ffdc_collector( |
| os_host, |
| os_username, |
| os_password, |
| config, |
| location, |
| os_type, |
| protocol, |
| env_vars, |
| econfig, |
| log_level, |
| ) |
| os_ffdc.collect_ffdc() |
| |
| |
| def get_os_type(os_host, os_username, os_password): |
| os_type = None |
| |
| # If HOST_OS is pingable |
| if os.system("ping -c 1 " + os_host) == 0: |
| r""" |
| Open a ssh connection to targeted system. |
| """ |
| ssh_remoteclient = SSHRemoteclient(os_host, os_username, os_password) |
| |
| if ssh_remoteclient.ssh_remoteclient_login(): |
| # Find OS_TYPE |
| cmd_exit_code, err, response = ssh_remoteclient.execute_command( |
| "uname" |
| ) |
| os_type = response.strip() |
| |
| # If HOST_OS is linux, expands os_type to one of |
| # the 2 linux distros that have more details in ffdc_config.yaml |
| if os_type.upper() == "LINUX": |
| ( |
| cmd_exit_code, |
| err, |
| response, |
| ) = ssh_remoteclient.execute_command("cat /etc/os-release") |
| linux_distro = response |
| if "redhat" in linux_distro: |
| os_type = "RHEL" |
| elif "ubuntu" in linux_distro: |
| os_type = "UBUNTU" |
| |
| if ssh_remoteclient: |
| ssh_remoteclient.ssh_remoteclient_disconnect() |
| |
| return os_type |