ffdc: Integrate ffdc script into robot framework flow.
This commit provides interface to enable automation tests (robot/jenkins)
to activate the new cli ffdc collector.
- Patchset 1: Initial commit for review.
- Patchset 2: Redesing and fixing issues
- Patchset 3: Fix build issue (pycodestyle)
- Patchset 4: Default ffdc store location running direct CLI
- Patchset 5: Addressing review comments and questions
- Patchset 6: Restore direct CLI default location to /tmp
- Patchset 7: Addressing issues from comments
Also extend socket timeout for long-running command peltool -a
- Patchset 8: Use Builtin().log_to_console("") method in the bridge code
- Patchset 9: Rebase
Tests:
- Standalone script: python3 ./ffdc/collect_ffdc.py
- Within robot env: python3 -m robot .... -v FFDC_DEFAULT:0 ./tools/myffdc.robot
Signed-off-by: Peter D Phan <peterp@us.ibm.com>
Change-Id: Ic892c48efe7dbdb3a4345ba89c3a0257f03a7ffb
diff --git a/ffdc/collect_ffdc.py b/ffdc/collect_ffdc.py
index 7711fd6..c1c9495 100644
--- a/ffdc/collect_ffdc.py
+++ b/ffdc/collect_ffdc.py
@@ -18,7 +18,7 @@
for found_dir in dirs:
sys.path.append(os.path.join(root, found_dir))
-from ffdc_collector import FFDCCollector
+from ffdc_collector import ffdc_collector
@click.command(context_settings=dict(help_option_names=['-h', '--help']))
@@ -61,26 +61,26 @@
click.echo("\n********** FFDC (First Failure Data Collection) Starts **********")
if input_options_ok(remote, username, password, config, type):
- thisFFDC = FFDCCollector(remote,
- username,
- password,
- config,
- location,
- type,
- protocol,
- env_vars,
- econfig,
- log_level)
- thisFFDC.collect_ffdc()
+ this_ffdc = ffdc_collector(remote,
+ username,
+ password,
+ config,
+ location,
+ type,
+ protocol,
+ env_vars,
+ econfig,
+ log_level)
+ this_ffdc.collect_ffdc()
- if len(os.listdir(thisFFDC.ffdc_dir_path)) == 0:
+ if len(os.listdir(this_ffdc.ffdc_dir_path)) == 0:
click.echo("\n\tFFDC Collection from " + remote + " has failed.\n\n")
else:
- click.echo(str("\n\t" + str(len(os.listdir(thisFFDC.ffdc_dir_path)))
+ click.echo(str("\n\t" + str(len(os.listdir(this_ffdc.ffdc_dir_path)))
+ " files were retrieved from " + remote))
- click.echo("\tFiles are stored in " + thisFFDC.ffdc_dir_path)
+ click.echo("\tFiles are stored in " + this_ffdc.ffdc_dir_path)
- click.echo("\tTotal elapsed time " + thisFFDC.elapsed_time + "\n\n")
+ click.echo("\tTotal elapsed time " + this_ffdc.elapsed_time + "\n\n")
click.echo("\n********** FFDC Finishes **********\n\n")
diff --git a/ffdc/ffdc_collector.py b/ffdc/ffdc_collector.py
index 4a8cfa4..61590a3 100644
--- a/ffdc/ffdc_collector.py
+++ b/ffdc/ffdc_collector.py
@@ -14,6 +14,8 @@
import platform
from errno import EACCES, EPERM
import subprocess
+
+sys.path.extend([f'./{name[0]}' for name in os.walk(".") if os.path.isdir(name[0])])
from ssh_utility import SSHRemoteclient
from telnet_utility import TelnetRemoteclient
@@ -33,8 +35,8 @@
- arg1
- arg2
"""
-abs_path = os.path.abspath(os.path.dirname(sys.argv[0]))
-plugin_dir = abs_path + '/plugins'
+plugin_dir = __file__.split(__file__.split("/")[-1])[0] + '/plugins'
+sys.path.append(plugin_dir)
try:
for module in os.listdir(plugin_dir):
if module == '__init__.py' or module[-3:] != '.py':
@@ -98,7 +100,7 @@
}
-class FFDCCollector:
+class ffdc_collector:
r"""
Execute commands from configuration file to collect log files.
@@ -154,9 +156,9 @@
# to be sure that all files for this run will have same timestamps
# and they will be saved in the same directory.
# self.location == local system for now
- self.set_ffdc_defaults()
+ self.set_ffdc_default_store_path()
- # Logger for this run. Need to be after set_ffdc_defaults()
+ # Logger for this run. Need to be after set_ffdc_default_store_path()
self.script_logging(getattr(logging, log_level.upper()))
# Verify top level directory exists for storage
@@ -181,7 +183,7 @@
# Load ENV vars from user.
self.logger.info("\n\tENV: User define input YAML variables")
self.env_dict = {}
- self. load_env()
+ self.load_env()
def verify_script_env(self):
@@ -686,7 +688,7 @@
progress_counter += 1
self.print_progress(progress_counter)
- def set_ffdc_defaults(self):
+ def set_ffdc_default_store_path(self):
r"""
Set a default value for self.ffdc_dir_path and self.ffdc_prefix.
Collected ffdc file will be stored in dir /self.location/hostname_timestr/.
@@ -704,7 +706,11 @@
self.ffdc_prefix = timestr + "_"
self.validate_local_store(self.ffdc_dir_path)
- def validate_local_store(self, dir_path):
+ # Need to verify local store path exists prior to instantiate this class.
+ # This class method is used to share the same code between CLI input parm
+ # and Robot Framework "${EXECDIR}/logs" before referencing this class.
+ @classmethod
+ def validate_local_store(cls, dir_path):
r"""
Ensure path exists to store FFDC files locally.
@@ -916,7 +922,7 @@
def execute_plugin_block(self, plugin_cmd_list):
r"""
- Pack the plugin command to quailifed python string object.
+ Pack the plugin command to qualifed python string object.
Description of argument(s):
plugin_list_dict Plugin block read from YAML
diff --git a/ffdc/ffdc_config.yaml b/ffdc/ffdc_config.yaml
index 1f7e041..b2bd403 100644
--- a/ffdc/ffdc_config.yaml
+++ b/ffdc/ffdc_config.yaml
@@ -61,7 +61,7 @@
- 'cat /var/log/obmc-console.log >/tmp/BMC_obmc_console.txt'
- 'cat /var/log/obmc-console1.log >/tmp/BMC_obmc_console1.txt'
- 'peltool -l >/tmp/PEL_logs_list.json'
- - 'peltool -a >/tmp/PEL_logs_display.json'
+ - {'peltool -a >/tmp/PEL_logs_display.json':240}
- 'hexdump -C /var/lib/phosphor-logging/extensions/pels/badPEL >/tmp/PEL_logs_badPEL.txt'
- 'guard -l >/tmp/GUARD_list.txt'
- 'killall -s SIGUSR1 pldmd; sleep 5'
diff --git a/ffdc/plugins/redfish.py b/ffdc/plugins/redfish.py
index 33a0669..0ea7a00 100644
--- a/ffdc/plugins/redfish.py
+++ b/ffdc/plugins/redfish.py
@@ -82,7 +82,7 @@
response = execute_redfish_cmd(parms + resource)
# Enumeration is done for available resources ignoring the
# ones for which response is not obtained.
- if 'Response Error' in response:
+ if 'Error getting response' in response:
continue
walk_nested_dict(response, url=resource)