blob: d31aa2da600aeae9f3776680cc4ebe350c9be6fe [file] [log] [blame]
#!/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