Test to do repeated, random boots

Utilizes additional keywords:
    Validate Connection
    Intersect Lists
    Search List

Change-Id: I29a2a4805bb685a0519d4e0f7eec5ab1568edca0
Signed-off-by: Gunnar Mills <gmills@us.ibm.com>
diff --git a/lib/connection_client.robot b/lib/connection_client.robot
index 5616071..7e88882 100755
--- a/lib/connection_client.robot
+++ b/lib/connection_client.robot
@@ -68,3 +68,69 @@
 
     ${https_num}=   Convert To Integer    ${HTTPS_PORT}
     Set Global Variable     ${AUTH_URI}    https://${OPENBMC_HOST}:${https_num}
+
+Validate Or Open Connection
+    [Documentation]  Checks for an open connection to a host or alias.
+    [Arguments]  ${alias}=None  ${host}=${EMPTY}  &{connection_args}
+
+    # alias            The alias of the connection to validate.
+    # host             The DNS name or IP of the host to validate.
+    # connection_args  A dictionary of arguments to pass to Open Conection
+    #                  and Log In (see above) if the connection is not open. May
+    #                  contain, but does not need to contain, the host or alias.
+
+    # Check to make sure we have an alias or host to search for.
+    Run Keyword If  '${host}' == '${EMPTY}'  Should Not Be Equal  ${alias}  None
+    ...  msg=Need to provide a host or an alias.  values=False
+
+    # Search the dictionary to see if it includes the host and alias.
+    ${host_exists}=  Run Keyword and Return Status
+    ...              Dictionary Should Contain Key  ${connection_args}  host
+    ${alias_exists}=  Run Keyword and Return Status
+    ...               Dictionary Should Contain Key  ${connection_args}  alias
+
+    # Add the alias and host back into the dictionary of connection arguments,
+    # if needed.
+    Run Keyword If  '${host}' != '${EMPTY}' and ${host_exists} == ${FALSE}
+    ...             Set to Dictionary  ${connection_args}  host  ${host}
+    Run Keyword If  '${alias}' != 'None' and ${alias_exists} == ${FALSE}
+    ...             Set to Dictionary  ${connection_args}  alias  ${alias}
+
+    @{open_connections}=  Get Connections
+    # If there are no open connections, open one and return.
+    Run Keyword If  '${open_connections}' == '[]'
+    ...             Open Connection and Log In  &{connection_args}
+    Return From Keyword If  '${open_connections}' == '[]'
+
+    # Connect to the alias or host that matches. If both are given, only connect
+    # to a connection that has both.
+    :FOR  ${connection}  IN  @{open_connections}
+    \  Log  ${connection}
+    \  ${alias_match}=  Evaluate  '${alias}' == '${connection.alias}'
+    \  ${host_match}=  Evaluate  '${host}' == '${connection.host}'
+    \  ${given_alias}=  Evaluate  '${alias}' != 'None'
+    \  ${no_alias}=  Evaluate  '${alias}' == 'None'
+    \  ${given_host}=  Evaluate  '${host}' != '${EMPTY}'
+    \  ${no_host}=  Evaluate  '${host}' == '${EMPTY}'
+    \  Run Keyword If
+    ...    ${given_alias} and ${given_host} and ${alias_match} and ${host_match}
+    ...    Run Keywords
+    ...      Switch Connection  ${alias}  AND
+    ...      Log to Console  Found connection. Switched to ${alias} ${host}  AND
+    ...      Return From Keyword If  ${alias_match} and ${host_match}
+    ...    ELSE  Run Keyword If
+    ...      ${given_alias} and ${no_host} and ${alias_match}
+    ...      Run Keywords
+    ...        Switch Connection  ${alias}  AND
+    ...        Log to Console  Found connection. Switched to: ${alias}  AND
+    ...        Return From Keyword If  ${alias_match}
+    ...    ELSE  Run Keyword If
+    ...       ${given_host} and ${no_alias} and ${host_match}
+    ...       Run Keywords
+    ...         Switch Connection  ${connection.index}  AND
+    ...         Log to Console  Found Connection. Switched to: ${host}  AND
+    ...         Return From Keyword If  ${host_match}
+
+    # If no connections are found, open a connection with the provided args.
+    Log  No connection with provided arguments.  Opening a connection.
+    Open Connection and Log In  &{connection_args}
diff --git a/lib/dvt/obmc_call_points.robot b/lib/dvt/obmc_call_points.robot
new file mode 100644
index 0000000..1d8db7c
--- /dev/null
+++ b/lib/dvt/obmc_call_points.robot
@@ -0,0 +1,36 @@
+*** Settings ***
+Documentation  This module contains keywords within tests/obmc_boot_test that
+...  are points at which to call plug-ins.
+
+Resource  obmc_driver_vars.txt
+
+*** Keywords ***
+Call Point Setup
+    [Documentation]  Call any plugins that have a cp_setup program
+    [Teardown]  Log to Console  **Plugin** end call point: cp_setup${\n}
+
+    Log to Console  ${\n}**Plugin** start call point: cp_setup
+
+Call Point Pre Boot
+    [Documentation]  Call any plugins that have a cp_pre_boot program
+    [Teardown]  Log to Console  **Plugin** end call point: cp_pre_boot${\n}
+
+    Log to Console  ${\n}**Plugin** start call point: cp_pre_boot
+
+Call Point Post Boot
+    [Documentation]  Call any plugins that have a cp_post_boot program
+    [Teardown]  Log to Console  **Plugin** end call point: cp_post_boot${\n}
+
+    Log to Console  ${\n}**Plugin** start call point: cp_post_boot
+
+Call Point FFDC
+    [Documentation]  Call any plugins that have a cp_ffdc program
+    [Teardown]  Log to Console  **Plugin** end call point: cp_ffdc${\n}
+
+    Log to Console  ${\n}**Plugin** start call point: cp_ffdc
+
+Call Point Stop Check
+    [Documentation]  Call any plugins that have a cp_stop_check program
+    [Teardown]  Log to Console  **Plugin** end call point: cp_stop_check${\n}
+
+    Log to Console  ${\n}**Plugin** start call point: cp_stop_check
diff --git a/lib/dvt/obmc_driver_vars.txt b/lib/dvt/obmc_driver_vars.txt
new file mode 100644
index 0000000..41bc6eb
--- /dev/null
+++ b/lib/dvt/obmc_driver_vars.txt
@@ -0,0 +1,35 @@
+*** Settings ***
+Documentation  This file includes all the varaibles used by obmc_boot_test.robot
+
+*** Variables ***
+# Alias of the master connection to the BMC
+${master_alias}  master
+
+# The count of the IPL we're currently doing - used in the FOR loop
+${IPL_COUNT}  ${0}
+
+# The total number of IPLs we plan on doing
+${IPL_TOTAL}  ${3}
+
+# The total number of IPLs that have passed and failed
+${IPL_PASSED}  ${0}
+${IPL_FAILED}  ${0}
+
+# The status of the last IPL that finished
+${IPL_STATUS}  ${EMPTY}
+
+# A list of the last 10 IPLs that have been performed (see Log Last Ten)
+@{LAST_TEN}
+
+# A list of keywords of valid IPLs that can be performed
+@{VALID_POWER_ON}  BMC Power On
+@{VALID_POWER_OFF}  BMC Power Off
+#@{VALID_ACCYCLE}
+#@{VALID_REBOOT}
+
+# The master list of all IPLs possible, for reference. (Currently not in use).
+@{MASTER_IPL_LIST}  BMC Power On  BMC Power Off
+
+# The list of available IPLs - Modifying this will limit what IPLs can be done.
+# This list is also used by: Setup Run Table, Log Run Table
+@{AVAIL_IPLS}  BMC Power On  BMC Power Off
diff --git a/lib/list_utils.robot b/lib/list_utils.robot
new file mode 100644
index 0000000..472294b
--- /dev/null
+++ b/lib/list_utils.robot
@@ -0,0 +1,32 @@
+*** Settings ***
+Documentation  This module contains keywords for list manipulation.
+Library  Collections
+
+*** Keywords ***
+Intersect Lists
+    [Documentation]  Intersects the two lists passed in. Returns a list of
+    ...  values common to both lists with no duplicates.
+    [Arguments]  ${list1}  ${list2}
+
+    # list1      The first list to intersect.
+    # list2      The second list to intersect.
+
+    ${length1}=  Get Length  ${list1}
+    ${length2}=  Get Length  ${list2}
+
+    @{intersected_list}  Create List
+
+    @{larger_list}=  Set Variable If  ${length1} >= ${length2}  ${list1}
+    ...                               ${length1} < ${length2}  ${list2}
+    @{smaller_list}=  Set Variable If  ${length1} >= ${length2}  ${list2}
+    ...                                ${length1} < ${length2}  ${list1}
+
+    :FOR  ${element}  IN  @{larger_list}
+    \  ${rc}=  Run Keyword and Return Status  List Should Contain Value  ${smaller_list}
+    ...  ${element}
+    \  Run Keyword If  '${rc}' == 'True'  Append to List  ${intersected_list}
+    ...  ${element}
+
+    @{intersected_list}=  Remove Duplicates  ${intersected_list}
+
+    [return]  @{intersected_list}