New poweroffs.py, powerons.py and gen_robot_plug_in.py.
Change-Id: I237dd5aab7a29466c6ec69451df9318415ea765f
Signed-off-by: Michael Walsh <micwalsh@us.ibm.com>
diff --git a/lib/boot/poweroffs.py b/lib/boot/poweroffs.py
new file mode 100755
index 0000000..55bb9bf
--- /dev/null
+++ b/lib/boot/poweroffs.py
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+
+r"""
+This module is the python counterpart to poweroffs.robot. It provides
+functions for powering off an open bmc machine.
+"""
+
+import gen_robot_print as grp
+import state as state_mod
+
+from robot.libraries.BuiltIn import BuiltIn
+
+# We need utils.robot to get keyword "Initiate Power Off".
+BuiltIn().import_resource("utils.robot")
+
+
+###############################################################################
+def bmc_power_off():
+
+ r"""
+ Power the Open BMC machine off and monitor status to verify.
+ """
+
+ grp.rprint_timen("Refreshing state data.")
+ state = state_mod.get_state()
+ grp.rprint_var(state)
+
+ match_state = state_mod.anchor_state(state)
+
+ grp.rprintn()
+ cmd_buf = ["Initiate Power Off"]
+ grp.rpissuing_keyword(cmd_buf)
+ power = BuiltIn().run_keyword(*cmd_buf)
+
+ # Wait for the state to change in any way.
+ state_mod.wait_state(match_state, wait_time="1 min", interval="3 seconds",
+ invert=1)
+
+ cmd_buf = ["Create Dictionary", "power=${0}",
+ "bmc=HOST_POWERED_OFF", "boot_progress=Off"]
+ grp.rdpissuing_keyword(cmd_buf)
+ final_state = BuiltIn().run_keyword(*cmd_buf)
+
+ final_state = state_mod.anchor_state(final_state)
+
+ grp.rprintn()
+ state_mod.wait_state(final_state, wait_time="2 min", interval="3 seconds")
+
+###############################################################################
diff --git a/lib/boot/powerons.py b/lib/boot/powerons.py
new file mode 100755
index 0000000..872912a
--- /dev/null
+++ b/lib/boot/powerons.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env python
+
+r"""
+This module is the python counterpart to utils.robot. It provides many
+functions for communicating with the Open BMC machine.
+"""
+
+import gen_robot_print as grp
+import state as state_mod
+
+from robot.libraries.BuiltIn import BuiltIn
+
+# We need utils.robot to get keyword "Initiate Power On".
+BuiltIn().import_resource("utils.robot")
+
+
+###############################################################################
+def bmc_power_on():
+
+ r"""
+ Power the Open BMC machine on and monitor status to verify.
+ """
+
+ grp.rprint_timen("Refreshing state data.")
+ state = state_mod.get_state()
+ grp.rprint_var(state)
+
+ match_state = state_mod.anchor_state(state)
+
+ grp.rprintn()
+ cmd_buf = ["Initiate Power On", "wait=${0}"]
+ grp.rpissuing_keyword(cmd_buf)
+ power = BuiltIn().run_keyword(*cmd_buf)
+
+ # Wait for the state to change in any way.
+ state_mod.wait_state(match_state, wait_time="1 min", interval="3 seconds",
+ invert=1)
+
+ cmd_buf = ["Create Dictionary", "power=${1}",
+ "bmc=HOST_BOOTED",
+ "boot_progress=FW Progress, Starting OS"]
+ grp.rdpissuing_keyword(cmd_buf)
+ final_state = BuiltIn().run_keyword(*cmd_buf)
+
+ try:
+ os_host = BuiltIn().get_variable_value("${OS_HOST}")
+ except TypeError:
+ os_host = ""
+
+ if os_host != "":
+ final_state['os_ping'] = 1
+ final_state['os_login'] = 1
+ final_state['os_run_cmd'] = 1
+
+ final_state = state_mod.anchor_state(final_state)
+
+ grp.rprintn()
+ state_mod.wait_state(final_state, wait_time="7 min", interval="3 seconds")
+
+###############################################################################
diff --git a/lib/gen_robot_plug_in.py b/lib/gen_robot_plug_in.py
new file mode 100755
index 0000000..9494365
--- /dev/null
+++ b/lib/gen_robot_plug_in.py
@@ -0,0 +1,224 @@
+#!/usr/bin/env python
+
+r"""
+This module provides functions which are useful for running plug-ins from a
+robot program.
+"""
+
+import sys
+import subprocess
+from robot.libraries.BuiltIn import BuiltIn
+import commands
+import os
+import tempfile
+
+import gen_print as gp
+import gen_robot_print as grp
+import gen_misc as gm
+
+
+###############################################################################
+def rvalidate_plug_ins(plug_in_dir_paths,
+ quiet=1):
+
+ r"""
+ Call the external validate_plug_ins.py program which validates the plug-in
+ dir paths given to it. Return a list containing a normalized path for
+ each plug-in selected.
+
+ Description of arguments:
+ plug_in_dir_paths A colon-separated list of plug-in
+ directory paths.
+ quiet If quiet is set to 1, this function will
+ NOT write status messages to stdout.
+ """
+
+ cmd_buf = "validate_plug_ins.py \"" + plug_in_dir_paths + "\""
+ if int(quiet) != 1:
+ grp.rpissuing(cmd_buf)
+ rc, out_buf = commands.getstatusoutput(cmd_buf)
+ if rc != 0:
+ message = gp.sprint_varx("rc", rc, 1) + out_buf
+ grp.rprintn(out_buf, 'STDERR')
+ BuiltIn().fail("Validate plug ins call failed. See stderr text for" +
+ " details.\n")
+
+ plug_in_packages_list = out_buf.split("\n")
+ if len(plug_in_packages_list) == 1 and plug_in_packages_list[0] == "":
+ return []
+
+ return plug_in_packages_list
+
+###############################################################################
+
+
+###############################################################################
+def rprocess_plug_in_packages(plug_in_packages_list=None,
+ call_point="setup",
+ shell_rc="0x00000000",
+ stop_on_plug_in_failure=1,
+ stop_on_non_zero_rc=0,
+ release_type="obmc",
+ quiet=None,
+ debug=None):
+
+ r"""
+ Call the external process_plug_in_packages.py to process the plug-in
+ packages. Return the following:
+ rc The return code - 0 = PASS, 1 = FAIL.
+ shell_rc The shell return code returned by
+ process_plug_in_packages.py.
+ failed_plug_in_name The failed plug in name (if any).
+
+ Description of arguments:
+ plug_in_packages_list A python list of plug-in directory paths.
+ call_point The call point program to be called for
+ each plug-in package (e.g. post_boot).
+ This name should not include the "cp_"
+ prefix.
+ shell_rc The user may supply a value other than
+ zero to indicate an acceptable non-zero
+ return code. For example, if this value
+ equals 0x00000200, it means that for each
+ plug-in call point that runs, a 0x00000200
+ will not be counted as a failure.
+ stop_on_plug_in_failure If this parameter is set to 1, this
+ program will stop and return non-zero if
+ the call point program from any plug-in
+ directory fails. Conversely, if it is set
+ to false, this program will run the call
+ point program from each and every plug-in
+ directory regardless of their return
+ values. Typical example cases where you'd
+ want to run all plug-in call points
+ regardless of success or failure would be
+ "cleanup" or "ffdc" call points.
+ stop_on_non_zero_rc If this parm is set to 1 and a plug-in
+ call point program returns a valid
+ non-zero return code (see "shell_rc" parm
+ above), this program will stop processing
+ and return 0 (success). Since this
+ constitutes a successful exit, this would
+ normally be used where the caller wishes
+ to stop processing if one of the plug-in
+ directory call point programs returns a
+ special value indicating that some special
+ case has been found. An example might be
+ in calling some kind of "check_errl" call
+ point program. Such a call point program
+ might return a 2 (i.e. 0x00000200) to
+ indicate that a given error log entry was
+ found in an "ignore" list and is therefore
+ to be ignored. That being the case, no
+ other "check_errl" call point program
+ would need to be called.
+ release_type The type of release being tested (e.g.
+ "obmc", "op", "fips"). This influences
+ which integrated plug-ins are selected.
+ quiet If quiet is set to 1, this function will
+ NOT write status messages to stdout. This
+ will default to the global quiet program
+ parm or to 0.
+ debug If this parameter is set to 1, this
+ function will print additional debug
+ information. This is mainly to be used by
+ the developer of this function. This will
+ default to the global quiet program parm
+ or to 0.
+ """
+
+ rc = 0
+
+ if plug_in_packages_list is None:
+ plug_in_packages_list = BuiltIn().get_variable_value(
+ "${plug_in_packages_list}")
+
+ # If there are no plug-in packages to process, return successfully.
+ if len(plug_in_packages_list) == 0:
+ return 0, 0, ""
+
+ if quiet is None:
+ try:
+ quiet = int(BuiltIn().get_variable_value("${quiet}"))
+ except TypeError:
+ quiet = 0
+
+ if debug is None:
+ try:
+ debug = int(BuiltIn().get_variable_value("${debug}"))
+ except TypeError:
+ debug = 0
+
+ # Create string from list.
+ plug_in_dir_paths = ':'.join(plug_in_packages_list)
+
+ temp = tempfile.NamedTemporaryFile()
+ temp_file_path = temp.name
+ temp2 = tempfile.NamedTemporaryFile()
+ temp_properties_file_path = temp2.name
+
+ if int(debug) == 1:
+ os.environ["PERF_TRACE"] = "1"
+ debug_string = " --quiet=0"
+ else:
+ debug_string = ""
+
+ loc_shell_rc = 0
+
+ sub_cmd_buf = "process_plug_in_packages.py" + debug_string +\
+ " --call_point=" + call_point + " --shell_rc=" +\
+ str(shell_rc) + " --stop_on_plug_in_failure=" +\
+ str(stop_on_plug_in_failure) + " --stop_on_non_zero_rc=" +\
+ str(stop_on_non_zero_rc) + " " + plug_in_dir_paths
+ if int(quiet) == 1:
+ cmd_buf = sub_cmd_buf + " > " + temp_file_path + " 2>&1"
+ else:
+ cmd_buf = "my_tee" + debug_string + " " + temp_file_path + " -c '" +\
+ sub_cmd_buf + "'"
+ if int(debug) == 1:
+ grp.rpissuing(cmd_buf)
+
+ ppc_rc = subprocess.call(cmd_buf, shell=True)
+
+ # As process_plug_in_packages.py help text states, it will print the
+ # values of failed_plug_in_name and shell_rc in the following format:
+ # failed_plug_in_name: <failed plug-in value, if any>
+ # shell_rc: <shell return code value of last
+ # call point program>
+
+ # We want to obtain those values from the output. To make the task
+ # simpler, we'll start by grepping the output for lines that might fit
+ # such a format:
+ # - Zero or more spaces
+ # - One or more non-colon characters
+ # - A colon
+ # - Zero or more spaces
+ cmd_buf = "egrep '^[ ]*[^:]+:[ ]*' " + temp_file_path + " > " +\
+ temp_properties_file_path
+ if int(debug) == 1:
+ grp.rpissuing(cmd_buf)
+ rc = os.system(cmd_buf)
+
+ # Next we call my_parm_file to create a properties dictionary.
+ properties = gm.my_parm_file(temp_properties_file_path)
+
+ # Finally, we access the 2 values that we need.
+ try:
+ shell_rc = properties['shell_rc']
+ except KeyError:
+ shell_rc = 0
+ try:
+ failed_plug_in_name = properties['failed_plug_in_name']
+ except KeyError:
+ failed_plug_in_name = ""
+
+ if rc != 0 or ppc_rc != 0:
+ grp.rprint_error("Call to process_plug_in_packages failed.\n")
+ grp.rprint_varx("rc", rc)
+ grp.rprint_varx("ppc_rc", ppc_rc)
+ grp.rprint_varx("shell_rc", shell_rc)
+ grp.rprint_varx("failed_plug_in_name", failed_plug_in_name)
+
+ return rc, shell_rc, failed_plug_in_name
+
+###############################################################################