ffdc: Add code to handle RHEL, UBUNTU, AIX remote hosts.
- Simplify remote host OS type in ffdc_confi;i.e. AIX_LINUX becomes AIX.
- Add code to handle RHEL, UBUNTU, AIX remote hosts.
Tests:
(1) First pass: successful (no error) code path with OPENHMC, RHEL, UBUNTU and AIX.
(@) Second pass: add tests to validate remote_host_type Vs. CLI input.
Signed-off-by: Peter D Phan <peterp@us.ibm.com>
Change-Id: I18cd353950372c19b0ffc731caebdaeac71bf043
Signed-off-by: Peter D Phan <peterp@us.ibm.com>
diff --git a/ffdc/collect_ffdc.py b/ffdc/collect_ffdc.py
index 49e89fa..eeeb79d 100644
--- a/ffdc/collect_ffdc.py
+++ b/ffdc/collect_ffdc.py
@@ -32,7 +32,9 @@
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")
-def cli_ffdc(remote, username, password, ffdc_config, location):
+@click.option('-t', '--remote_type', default="OPENBMC",
+ show_default=True, help="OS type of the remote (targeting) host. OPENBMC, RHEL, UBUNTU, AIX")
+def cli_ffdc(remote, username, password, ffdc_config, location, remote_type):
r"""
Stand alone CLI to generate and collect FFDC from the selected target.
"""
@@ -40,7 +42,7 @@
click.echo("\n********** FFDC (First Failure Data Collection) Starts **********")
if input_options_ok(remote, username, password, ffdc_config):
- thisFFDC = FFDCCollector(remote, username, password, ffdc_config, location)
+ thisFFDC = FFDCCollector(remote, username, password, ffdc_config, location, remote_type)
thisFFDC.collect_ffdc()
if not thisFFDC.receive_file_list:
diff --git a/ffdc/ffdc_collector.py b/ffdc/ffdc_collector.py
index 5b84106..873f563 100644
--- a/ffdc/ffdc_collector.py
+++ b/ffdc/ffdc_collector.py
@@ -21,7 +21,10 @@
"""
- def __init__(self, hostname, username, password, ffdc_config, location):
+ # List of supported OSes.
+ supported_oses = ['OPENBMC', 'RHEL', 'AIX', 'UBUNTU']
+
+ def __init__(self, hostname, username, password, ffdc_config, location, remote_type):
r"""
Description of argument(s):
@@ -29,7 +32,8 @@
username user on the targeted system with access to FFDC files
password password for user on targeted system
ffdc_config configuration file listing commands and files for FFDC
- location Where to store collected FFDC
+ location where to store collected FFDC
+ remote_type os type of the remote host
"""
if self.verify_script_env():
@@ -42,7 +46,7 @@
self.ffdc_dir_path = ""
self.ffdc_prefix = ""
self.receive_file_list = []
- self.target_type = ""
+ self.target_type = remote_type.upper()
else:
sys.exit(-1)
@@ -82,13 +86,54 @@
print("\n>>>>>\tERROR: %s is not ping-able. FFDC collection aborted.\n" % self.hostname)
sys.exit(-1)
- def set_target_machine_type(self):
+ def inspect_target_machine_type(self):
r"""
- Determine and set target machine type.
+ Inspect remote host os-release or uname.
"""
- # Default to openbmc for first few sprints
- self.target_type = "OPENBMC"
+ command = "cat /etc/os-release"
+ response = self.remoteclient.execute_command(command)
+ if response:
+ print("\n\t[INFO] %s /etc/os-release\n" % self.hostname)
+ print("\t\t %s" % self.find_os_type(response, 'PRETTY_NAME'))
+ 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 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
+ for each_os in FFDCCollector.supported_oses:
+ if each_os in identity:
+ self.target_type = each_os
+ break
+ 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"""
@@ -104,7 +149,7 @@
working_protocol_list.append("SSH")
# Verify top level directory exists for storage
self.validate_local_store(self.location)
- self.set_target_machine_type()
+ self.inspect_target_machine_type()
print("\n\t---- Completed protocol pre-requisite check ----\n")
self.generate_ffdc(working_protocol_list)
@@ -129,8 +174,10 @@
def generate_ffdc(self, working_protocol_list):
r"""
- Send commands in ffdc_config file to targeted system.
+ Determine actions based on remote host type
+ Description of argument(s):
+ working_protocol_list list of confirmed working protocols to connect to remote host.
"""
print("\n\t---- Executing commands on " + self.hostname + " ----")
@@ -139,34 +186,56 @@
ffdc_actions = yaml.load(file, Loader=yaml.FullLoader)
for machine_type in ffdc_actions.keys():
- if machine_type == self.target_type:
+ if machine_type == self.target_type:
if (ffdc_actions[machine_type]['PROTOCOL'][0] in working_protocol_list):
- print("\n\t[Run] Executing commands on %s using %s"
- % (self.hostname, ffdc_actions[machine_type]['PROTOCOL'][0]))
- list_of_commands = ffdc_actions[machine_type]['COMMANDS']
- progress_counter = 0
- for command in list_of_commands:
- self.remoteclient.execute_command(command)
- progress_counter += 1
- self.print_progress(progress_counter)
- print("\n\t[Run] Commands execution completed.\t\t [OK]")
+ # For RHEL and UBUNTU, collect common Linux FFDC.
+ if self.target_type == 'RHEL' \
+ or self.target_type == 'UBUNTU':
- if self.remoteclient.scpclient:
- print("\n\n\tCopying FFDC files from remote system %s.\n" % self.hostname)
- # Get default values for scp action.
- # self.location == local system for now
- self.set_ffdc_defaults()
- # Retrieving files from target system
- list_of_files = ffdc_actions[machine_type]['FILES']
- self.scp_ffdc(self.ffdc_dir_path, self.ffdc_prefix, list_of_files)
- else:
- print("\n\n\tSkip copying FFDC files from remote system %s.\n" % self.hostname)
+ self.collect_and_copy_ffdc(ffdc_actions['LINUX'])
+
+ # Collect remote host specific FFDC.
+ self.collect_and_copy_ffdc(ffdc_actions[machine_type])
else:
print("\n\tProtocol %s is not yet supported by this script.\n"
% ffdc_actions[machine_type]['PROTOCOL'][0])
+ # Close network connection after collecting all files
+ self.remoteclient.ssh_remoteclient_disconnect()
+
+ def collect_and_copy_ffdc(self,
+ ffdc_actions_for_machine_type):
+ 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.
+ """
+
+ 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:
+ self.remoteclient.execute_command(command)
+ progress_counter += 1
+ self.print_progress(progress_counter)
+
+ print("\n\t[Run] Commands execution completed.\t\t [OK]")
+
+ if self.remoteclient.scpclient:
+ print("\n\n\tCopying FFDC files from remote system %s.\n" % self.hostname)
+ # Get default values for scp action.
+ # self.location == local system for now
+ self.set_ffdc_defaults()
+ # Retrieving files from target system
+ list_of_files = ffdc_actions_for_machine_type['FILES']
+ self.scp_ffdc(self.ffdc_dir_path, self.ffdc_prefix, list_of_files)
+ else:
+ print("\n\n\tSkip copying FFDC files from remote system %s.\n" % self.hostname)
+
def scp_ffdc(self,
targ_dir_path,
targ_file_prefix="",
@@ -183,7 +252,6 @@
"""
- self.receive_file_list = []
progress_counter = 0
for filename in file_list:
source_file_path = filename
@@ -204,8 +272,6 @@
progress_counter += 1
self.print_progress(progress_counter)
- self.remoteclient.ssh_remoteclient_disconnect()
-
def set_ffdc_defaults(self):
r"""
Set a default value for self.ffdc_dir_path and self.ffdc_prefix.
diff --git a/ffdc/ffdc_config.yaml b/ffdc/ffdc_config.yaml
index 5a3d830..035745c 100644
--- a/ffdc/ffdc_config.yaml
+++ b/ffdc/ffdc_config.yaml
@@ -9,6 +9,9 @@
# Note: Items in COMMANDS and FILES are not necessarily one-to-one correspondence.
# For example, a file could have been created by an internal process,
# and is listed in FILES to be collected.
+#
+# Note: When a new remote type is added to this configuration file,
+# it is also need to be added the list of supported OSes in ffdc_lollector.py
# Commands and Files to collect for a given OpenBMC system.
OPENBMC:
@@ -81,7 +84,7 @@
- 'SSH'
# Commands and Files to collect for Ubuntu Linux only
-UBUNTU_LINUX:
+UBUNTU:
COMMANDS:
- '{ lsusb -t ; lsusb -v ; } >/tmp/OS_isub.txt 2>&1'
- 'tail -n 50000 /var/log/kern.log >/tmp/OS_kern.txt 2>&1'
@@ -101,7 +104,7 @@
- 'SSH'
# Commands and Files to collect for RHE Linux only
-RHEL_LINUX:
+RHEL:
COMMANDS:
- '/usr/bin/ctversion -bv >/tmp/OS_rsct.txt 2>&1'
- 'cat /var/log/secure >/tmp/OS_secure.txt 2>&1'
@@ -119,7 +122,7 @@
- 'SSH'
# Commands and Files to collect for AIX only
-AIX_LINUX:
+AIX:
COMMANDS:
- 'errpt >/tmp/OS_errpt.txt 2>&1 ; errclear 0;'
- 'bindprocessor -q >/tmp/OS_processors.txt 2>&1'