ffdc: Add code to handle OEM OSes
- Set 1: Initial code to handle OEM OSes.
- Set 2: Modify commit message.
- Set 3: Flag error when user input OS type is not described in config file.
Test:
- Set 1: Regressing tests to OpenBmc, RHEL, Ubuntu, AIX, OEM
Signed-off-by: Peter D Phan <peterp@us.ibm.com>
Change-Id: Id5410d21c7e4f8f5e74f1dded212b935075f7bea
diff --git a/ffdc/collect_ffdc.py b/ffdc/collect_ffdc.py
index 1915b2a..1153739 100644
--- a/ffdc/collect_ffdc.py
+++ b/ffdc/collect_ffdc.py
@@ -32,8 +32,7 @@
show_default=True, help="YAML Configuration file listing commands and files for FFDC.")
@click.option('-l', '--location', default="/tmp",
show_default=True, help="Location to store collected FFDC data")
-@click.option('-t', '--remote_type', default="OPENBMC",
- show_default=True,
+@click.option('-t', '--remote_type',
help="OS type of the remote (targeting) host. OPENBMC, RHEL, UBUNTU, AIX")
@click.option('-rp', '--remote_protocol', default="ALL",
show_default=True,
@@ -46,7 +45,7 @@
click.echo("\n********** FFDC (First Failure Data Collection) Starts **********")
- if input_options_ok(remote, username, password, ffdc_config):
+ if input_options_ok(remote, username, password, ffdc_config, remote_type):
thisFFDC = FFDCCollector(remote, username, password,
ffdc_config, location, remote_type, remote_protocol)
thisFFDC.collect_ffdc()
@@ -62,7 +61,7 @@
click.echo("\n********** FFDC Finishes **********\n\n")
-def input_options_ok(remote, username, password, ffdc_config):
+def input_options_ok(remote, username, password, ffdc_config, remote_type):
r"""
Verify script options exist via CLI options or environment variables.
"""
@@ -82,6 +81,10 @@
print("\
\n>>>>>\tERROR: Password for user on remote host is not specified in CLI options "
+ "or env OPENBMC_PASSWORD.")
+ if not remote_type:
+ all_options_ok = False
+ print("\
+ \n>>>>>\tERROR: Remote host os type is not specified in CLI options.")
if not os.path.isfile(ffdc_config):
all_options_ok = False
print("\
diff --git a/ffdc/ffdc_collector.py b/ffdc/ffdc_collector.py
index 2604650..3657136 100644
--- a/ffdc/ffdc_collector.py
+++ b/ffdc/ffdc_collector.py
@@ -61,8 +61,9 @@
with open(self.ffdc_config, 'r') as file:
self.ffdc_actions = yaml.load(file, Loader=yaml.FullLoader)
- # List of supported OSes.
- self.supported_oses = self.ffdc_actions['DISTRO_OS'][0]
+ if self.target_type not in self.ffdc_actions.keys():
+ print("\n\tERROR: %s is not listed in %s.\n\n" % (self.target_type, self.ffdc_config))
+ sys.exit(-1)
def verify_script_env(self):
@@ -106,69 +107,6 @@
print("\n>>>>>\tERROR: %s is not ping-able. FFDC collection aborted.\n" % self.hostname)
sys.exit(-1)
- def inspect_target_machine_type(self):
- r"""
- Inspect remote host os-release or uname.
-
- """
- print("\n\tSupported distro: %s" % self.supported_oses)
-
- command = "cat /etc/os-release"
- response = self.remoteclient.execute_command(command)
- if response:
- print("\n\t[INFO] %s /etc/os-release\n" % self.hostname)
- for each_info in response:
- print("\t\t %s" % each_info)
- identity = self.find_os_type(response, 'ID').split('=')[1].upper()
- else:
- response = self.remoteclient.execute_command('uname -a')
- print("\n\t[INFO] %s uname -a\n" % self.hostname)
- print("\t\t %s" % ' '.join(response))
- identity = self.find_os_type(response, 'AIX').split(' ')[0].upper()
-
- # If OS does not have /etc/os-release and is not AIX,
- # script does not yet know what to do.
- if not identity:
- print(">>>>>\tERROR: Script does not yet know about %s" % ' '.join(response))
- sys.exit(-1)
-
- if (self.target_type not in identity):
-
- user_target_type = self.target_type
- self.target_type = ""
- for each_os in self.supported_oses:
- if each_os in identity:
- self.target_type = each_os
- break
-
- # If OS in not one of ['OPENBMC', 'RHEL', 'AIX', 'UBUNTU']
- # script does not yet know what to do.
- if not self.target_type:
- print(">>>>>\tERROR: Script does not yet know about %s" % identity)
- sys.exit(-1)
-
- print("\n\t[WARN] user request %s does not match remote host type %s.\n"
- % (user_target_type, self.target_type))
- print("\t[WARN] FFDC collection continues for %s.\n" % self.target_type)
-
- def find_os_type(self,
- listing_from_os,
- key):
- r"""
- Return OS information with the requested key
-
- Description of argument(s):
-
- listing_from_os list of information returns from OS command
- key key of the desired data
-
- """
-
- for each_item in listing_from_os:
- if key in each_item:
- return each_item
- return ''
-
def collect_ffdc(self):
r"""
Initiate FFDC Collection depending on requested protocol.
@@ -189,17 +127,16 @@
working_protocol_list.append("REDFISH")
print("\n\t[Check] %s Redfish Service.\t\t [OK]" % self.hostname)
else:
- print("\n\t[Check] %s Redfish Service.\t\t [FAILED]" % self.hostname)
+ print("\n\t[Check] %s Redfish Service.\t\t [NOT AVAILABLE]" % self.hostname)
if self.verify_ipmi():
working_protocol_list.append("IPMI")
print("\n\t[Check] %s IPMI LAN Service.\t\t [OK]" % self.hostname)
else:
- print("\n\t[Check] %s IPMI LAN Service.\t\t [FAILED]" % self.hostname)
+ print("\n\t[Check] %s IPMI LAN Service.\t\t [NOT AVAILABLE]" % self.hostname)
# Verify top level directory exists for storage
self.validate_local_store(self.location)
- self.inspect_target_machine_type()
print("\n\t---- Completed protocol pre-requisite check ----\n")
if ((self.remote_protocol not in working_protocol_list) and (self.remote_protocol != 'ALL')):
@@ -261,13 +198,22 @@
continue
if ffdc_actions[machine_type][k]['PROTOCOL'][0] == 'SSH':
- self.protocol_ssh(ffdc_actions, machine_type, k)
+ if 'SSH' in working_protocol_list:
+ self.protocol_ssh(ffdc_actions, machine_type, k)
+ else:
+ print("\n\tERROR: SSH is not available for %s." % self.hostname)
if ffdc_actions[machine_type][k]['PROTOCOL'][0] == 'REDFISH':
- self.protocol_redfish(ffdc_actions, machine_type, k)
+ if 'REDFISH' in working_protocol_list:
+ self.protocol_redfish(ffdc_actions, machine_type, k)
+ else:
+ print("\n\tERROR: REDFISH is not available for %s." % self.hostname)
if ffdc_actions[machine_type][k]['PROTOCOL'][0] == 'IPMI':
- self.protocol_ipmi(ffdc_actions, machine_type, k)
+ if 'IPMI' in working_protocol_list:
+ self.protocol_ipmi(ffdc_actions, machine_type, k)
+ else:
+ print("\n\tERROR: IMPI is not available for %s." % self.hostname)
# Close network connection after collecting all files
self.elapsed_time = time.strftime("%H:%M:%S", time.gmtime(time.time() - self.start_time))
@@ -398,19 +344,11 @@
form_filename if true, pre-pend self.target_type to filename
"""
- print("\n\t[Run] Executing commands on %s using %s"
- % (self.hostname, ffdc_actions_for_machine_type['PROTOCOL'][0]))
- list_of_commands = ffdc_actions_for_machine_type['COMMANDS']
- progress_counter = 0
- for command in list_of_commands:
- if form_filename:
- command = str(command % self.target_type)
- self.remoteclient.execute_command(command)
- progress_counter += 1
- self.print_progress(progress_counter)
+ # Executing commands, , if any
+ self.ssh_execute_ffdc_commands(ffdc_actions_for_machine_type,
+ form_filename)
- print("\n\t[Run] Commands execution completed.\t\t [OK]")
-
+ # Copying files
if self.remoteclient.scpclient:
print("\n\n\tCopying FFDC files from remote system %s.\n" % self.hostname)
@@ -420,6 +358,43 @@
else:
print("\n\n\tSkip copying FFDC files from remote system %s.\n" % self.hostname)
+ def ssh_execute_ffdc_commands(self,
+ ffdc_actions_for_machine_type,
+ form_filename=False):
+ r"""
+ Send commands in ffdc_config file to targeted system.
+
+ Description of argument(s):
+ ffdc_actions_for_machine_type commands and files for the selected remote host type.
+ form_filename if true, pre-pend self.target_type to filename
+ """
+ print("\n\t[Run] Executing commands on %s using %s"
+ % (self.hostname, ffdc_actions_for_machine_type['PROTOCOL'][0]))
+ list_of_commands = ffdc_actions_for_machine_type['COMMANDS']
+
+ # If command list is empty, returns
+ if not list_of_commands:
+ return
+
+ progress_counter = 0
+ for command in list_of_commands:
+ if isinstance(command, dict):
+ command_txt = next(iter(command))
+ command_timeout = next(iter(command.values()))
+ elif isinstance(command, str):
+ command_txt = command
+ # Default ssh command timeout 60 seconds
+ command_timeout = 60
+
+ if form_filename:
+ command_txt = str(command_txt % self.target_type)
+
+ self.remoteclient.execute_command(command_txt, command_timeout)
+ progress_counter += 1
+ self.print_progress(progress_counter)
+
+ print("\n\t[Run] Commands execution completed.\t\t [OK]")
+
def group_copy(self,
ffdc_actions_for_machine_type):
r"""
@@ -428,6 +403,10 @@
Description of argument(s):
ffdc_actions_for_machine_type commands and files for the selected remote host type.
"""
+
+ # Executing commands, if any
+ self.ssh_execute_ffdc_commands(ffdc_actions_for_machine_type)
+
if self.remoteclient.scpclient:
print("\n\tCopying DUMP files from remote system %s.\n" % self.hostname)
diff --git a/ffdc/ssh_utility.py b/ffdc/ssh_utility.py
index 2110b74..44a76ff 100644
--- a/ffdc/ssh_utility.py
+++ b/ffdc/ssh_utility.py
@@ -70,7 +70,7 @@
if self.scpclient:
self.scpclient.close()
- def execute_command(self, command):
+ def execute_command(self, command, default_timeout=60):
"""
Execute command on the remote host.
@@ -80,7 +80,7 @@
"""
try:
- stdin, stdout, stderr = self.sshclient.exec_command(command)
+ stdin, stdout, stderr = self.sshclient.exec_command(command, timeout=default_timeout)
stdout.channel.recv_exit_status()
response = stdout.readlines()
return response