ffdc: Add base infrastructure to support redfish protocol.
- Set 1: Initial commit for review. Add -t BMC_GET for redfish.
- Set 2: Add new CLI option --remote_protocol (-rp).
Default: ALL available.
- Set 3: Enhance messaging for Refish path.
Test:
- All types to OpenBMC's, RHEL, Ubuntu and AIX.
- Regression test to OpenBMC's, RHEL, Ubuntu and AIX.
Signed-off-by: Peter D Phan <peterp@us.ibm.com>
Change-Id: I969a923b49cc38314cdc194a9e6de8acc3f89fdb
diff --git a/ffdc/collect_ffdc.py b/ffdc/collect_ffdc.py
index 0163512..48a849e 100644
--- a/ffdc/collect_ffdc.py
+++ b/ffdc/collect_ffdc.py
@@ -33,8 +33,13 @@
@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, help="OS type of the remote (targeting) host. OPENBMC, RHEL, UBUNTU, AIX")
-def cli_ffdc(remote, username, password, ffdc_config, location, remote_type):
+ show_default=True,
+ help="OS type of the remote (targeting) host. OPENBMC, RHEL, UBUNTU, AIX")
+@click.option('-rp', '--remote_protocol', default="ALL",
+ show_default=True,
+ help="Select protocol (SSH, SCP, REDFISH) to communicate with remote host. \
+ Default: all available.")
+def cli_ffdc(remote, username, password, ffdc_config, location, remote_type, remote_protocol):
r"""
Stand alone CLI to generate and collect FFDC from the selected target.
"""
@@ -42,13 +47,14 @@
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, remote_type)
+ thisFFDC = FFDCCollector(remote, username, password,
+ ffdc_config, location, remote_type, remote_protocol)
thisFFDC.collect_ffdc()
if len(os.listdir(thisFFDC.ffdc_dir_path)) == 0:
click.echo("\n\tFFDC Collection from " + remote + " has failed.\n\n")
else:
- click.echo(str("\t" + str(len(os.listdir(thisFFDC.ffdc_dir_path)))
+ click.echo(str("\n\t" + str(len(os.listdir(thisFFDC.ffdc_dir_path)))
+ " files were retrieved from " + remote))
click.echo("\tFiles are stored in " + thisFFDC.ffdc_dir_path + "\n\n")
diff --git a/ffdc/ffdc_collector.py b/ffdc/ffdc_collector.py
index e8652f4..6dbb530 100644
--- a/ffdc/ffdc_collector.py
+++ b/ffdc/ffdc_collector.py
@@ -10,6 +10,7 @@
import time
import platform
from errno import EACCES, EPERM
+import subprocess
from ssh_utility import SSHRemoteclient
@@ -24,7 +25,14 @@
# List of supported OSes.
supported_oses = ['OPENBMC', 'RHEL', 'AIX', 'UBUNTU']
- def __init__(self, hostname, username, password, ffdc_config, location, remote_type):
+ def __init__(self,
+ hostname,
+ username,
+ password,
+ ffdc_config,
+ location,
+ remote_type,
+ remote_protocol):
r"""
Description of argument(s):
@@ -46,6 +54,7 @@
self.ffdc_dir_path = ""
self.ffdc_prefix = ""
self.target_type = remote_type.upper()
+ self.remote_protocol = remote_protocol.upper()
else:
sys.exit(-1)
@@ -56,6 +65,9 @@
import paramiko
run_env_ok = True
+
+ redfishtool_version = self.run_redfishtool('-V').split(' ')[2]
+
print("\n\t---- Script host environment ----")
print("\t{:<10} {:<10}".format('Script hostname', os.uname()[1]))
print("\t{:<10} {:<10}".format('Script host os', platform.platform()))
@@ -63,6 +75,7 @@
print("\t{:<10} {:>10}".format('PyYAML', yaml.__version__))
print("\t{:<10} {:>10}".format('click', click.__version__))
print("\t{:<10} {:>10}".format('paramiko', paramiko.__version__))
+ print("\t{:<10} {:>10}".format('redfishtool', redfishtool_version))
if eval(yaml.__version__.replace('.', ',')) < (5, 4, 1):
print("\n\tERROR: Python or python packages do not meet minimum version requirement.")
@@ -108,7 +121,8 @@
print(">>>>>\tERROR: Script does not yet know about %s" % ' '.join(response))
sys.exit(-1)
- if self.target_type not in identity:
+ if (self.target_type not in identity):
+
user_target_type = self.target_type
self.target_type = ""
for each_os in FFDCCollector.supported_oses:
@@ -158,11 +172,27 @@
if self.ssh_to_target_system():
working_protocol_list.append("SSH")
working_protocol_list.append("SCP")
+
+ # Redfish
+ if self.verify_redfish():
+ 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)
+
# 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")
- self.generate_ffdc(working_protocol_list)
+
+ if ((self.remote_protocol not in working_protocol_list) and (self.remote_protocol != 'ALL')):
+ print("\n\tWorking protocol list: %s" % working_protocol_list)
+ print(
+ '>>>>>\tERROR: Requested protocol %s is not in working protocol list.\n'
+ % self.remote_protocol)
+ sys.exit(-1)
+ else:
+ self.generate_ffdc(working_protocol_list)
def ssh_to_target_system(self):
r"""
@@ -206,30 +236,89 @@
for machine_type in ffdc_actions.keys():
if machine_type == self.target_type:
- if (ffdc_actions[machine_type]['PROTOCOL'][0] in working_protocol_list):
+ if self.remote_protocol == 'SSH' or self.remote_protocol == 'ALL':
+ self.protocol_ssh(ffdc_actions, machine_type)
- # For OPENBMC collect general system info.
- if self.target_type == 'OPENBMC':
-
- self.collect_and_copy_ffdc(ffdc_actions['GENERAL'],
- form_filename=True)
- self.group_copy(ffdc_actions['OPENBMC_DUMPS'])
-
- # For RHEL and UBUNTU, collect common Linux OS FFDC.
- if self.target_type == 'RHEL' \
- or self.target_type == 'UBUNTU':
-
- 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])
+ if self.target_type == 'OPENBMC':
+ if self.remote_protocol == 'REDFISH' or self.remote_protocol == 'ALL':
+ self.protocol_redfish(ffdc_actions, 'OPENBMC_REDFISH')
# Close network connection after collecting all files
self.remoteclient.ssh_remoteclient_disconnect()
+ def protocol_ssh(self,
+ ffdc_actions,
+ machine_type):
+ r"""
+ Perform actions using SSH and SCP protocols.
+
+ Description of argument(s):
+ ffdc_actions List of actions from ffdc_config.yaml.
+ machine_type OS Type of remote host.
+ """
+
+ # For OPENBMC collect general system info.
+ if self.target_type == 'OPENBMC':
+
+ self.collect_and_copy_ffdc(ffdc_actions['GENERAL'],
+ form_filename=True)
+ self.group_copy(ffdc_actions['OPENBMC_DUMPS'])
+
+ # For RHEL and UBUNTU, collect common Linux OS FFDC.
+ if self.target_type == 'RHEL' \
+ or self.target_type == 'UBUNTU':
+
+ self.collect_and_copy_ffdc(ffdc_actions['LINUX'])
+
+ # Collect remote host specific FFDC.
+ self.collect_and_copy_ffdc(ffdc_actions[machine_type])
+
+ def protocol_redfish(self,
+ ffdc_actions,
+ machine_type):
+ r"""
+ Perform actions using Redfish protocol.
+
+ Description of argument(s):
+ ffdc_actions List of actions from ffdc_config.yaml.
+ machine_type OS Type of remote host.
+ """
+
+ print("\n\t[Run] Executing commands to %s using %s" % (self.hostname, 'REDFISH'))
+ redfish_files_saved = []
+ progress_counter = 0
+ list_of_URL = ffdc_actions[machine_type]['URL']
+ for index, each_url in enumerate(list_of_URL, start=0):
+ redfish_parm = '-u ' + self.username + ' -p ' + self.password + ' -r ' \
+ + self.hostname + ' -S Always raw GET ' + each_url
+
+ result = self.run_redfishtool(redfish_parm)
+ if result:
+ try:
+ targ_file = ffdc_actions[machine_type]['FILES'][index]
+ except IndexError:
+ targ_file = each_url.split('/')[-1]
+ print("\n\t[WARN] Missing filename to store data from redfish URL %s." % each_url)
+ print("\t[WARN] Data will be stored in %s." % targ_file)
+
+ targ_file_with_path = (self.ffdc_dir_path
+ + self.ffdc_prefix
+ + targ_file)
+
+ # Creates a new file
+ with open(targ_file_with_path, 'w') as fp:
+ fp.write(result)
+ fp.close
+ redfish_files_saved.append(targ_file)
+
+ progress_counter += 1
+ self.print_progress(progress_counter)
+
+ print("\n\t[Run] Commands execution completed.\t\t [OK]")
+
+ for file in redfish_files_saved:
+ print("\n\t\tSuccessfully save file " + file + ".")
+
def collect_and_copy_ffdc(self,
ffdc_actions_for_machine_type,
form_filename=False):
@@ -380,3 +469,35 @@
sys.stdout.write("\r\t" + "+" * progress)
sys.stdout.flush()
time.sleep(.1)
+
+ def verify_redfish(self):
+ r"""
+ Verify remote host has redfish service active
+
+ """
+ redfish_parm = '-u ' + self.username + ' -p ' + self.password + ' -r ' \
+ + self.hostname + ' -S Always raw GET /redfish/v1/'
+ return(self.run_redfishtool(redfish_parm, True))
+
+ def run_redfishtool(self,
+ parms_string,
+ quiet=False):
+ r"""
+ Run CLI redfishtool
+
+ Description of variable:
+ parms_string redfishtool subcommand and options.
+ quiet do not print redfishtool error message if True
+ """
+
+ result = subprocess.run(['redfishtool ' + parms_string],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ shell=True,
+ universal_newlines=True)
+
+ if result.stderr and not quiet:
+ print('\n\t\tERROR with redfishtool ' + parms_string)
+ print('\t\t' + result.stderr)
+
+ return result.stdout
diff --git a/ffdc/ffdc_config.yaml b/ffdc/ffdc_config.yaml
index 9146c13..38d539d 100644
--- a/ffdc/ffdc_config.yaml
+++ b/ffdc/ffdc_config.yaml
@@ -91,6 +91,17 @@
PROTOCOL:
- 'SSH'
+# URLs and Files for OPENBMC redfish
+# URLs and Files are one-to-one corresponding.
+# File contains the data returned from 'redfishtool GET URL'
+OPENBMC_REDFISH:
+ URL:
+ - '/xyz/openbmc_project/software/enumerate'
+ FILES:
+ - 'software.json'
+ PROTOCOL:
+ - 'REDFISH'
+
# Commands and Files to collect for all Linux distributions
LINUX:
COMMANDS:
diff --git a/ffdc/setup.py b/ffdc/setup.py
index 9f06bc0..f8c6b18 100644
--- a/ffdc/setup.py
+++ b/ffdc/setup.py
@@ -8,6 +8,7 @@
'click',
'PyYAML',
'paramiko',
+ 'redfishtool'
],
entry_points={
'console_scripts': ['collectFFDC=commands.install_cmd:main']
diff --git a/requirements.txt b/requirements.txt
index 1b497fd..8e1aaa3 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -6,4 +6,5 @@
robotframework-scplibrary
redfish
click
-PyYAML>=5.1
\ No newline at end of file
+PyYAML>=5.1
+redfishtool