|  | *** Settings *** | 
|  | Documentation    Remote logging test for rsyslog. | 
|  |  | 
|  | # Program arguments: | 
|  | # REMOTE_LOG_SERVER_HOST    The host name or IP address of the remote | 
|  | #                           logging server. | 
|  | # REMOTE_LOG_SERVER_PORT    The port number for the remote logging server. | 
|  | # REMOTE_USERNAME           The username for the remote logging server. | 
|  | # REMOTE_PASSWORD           The password for the remote logging server. | 
|  |  | 
|  | Library          String | 
|  | Resource         ../../lib/openbmc_ffdc.robot | 
|  | Resource         ../../lib/boot_utils.robot | 
|  | Resource         ../../lib/remote_logging_utils.robot | 
|  | Resource         ../../lib/bmc_redfish_resource.robot | 
|  | Resource         ../../lib/ipmi_client.robot | 
|  | Resource         ../../lib/bmc_redfish_resource.robot | 
|  | Resource         ../../lib/ipmi_client.robot | 
|  | Library          ../../lib/ipmi_utils.py | 
|  | Library          ../../lib/gen_misc.py | 
|  |  | 
|  | Suite Setup      Suite Setup Execution | 
|  | Test Setup       Test Setup Execution | 
|  | Test Teardown    FFDC On Test Case Fail | 
|  |  | 
|  | *** Variables *** | 
|  |  | 
|  | # Strings to check from journald. | 
|  | ${BMC_STOP_MSG}          Stopping Network IPMI daemon | 
|  | ${BMC_START_MSG}         Starting Flush Journal to Persistent Storage | 
|  | ${BMC_BOOT_MSG}          Startup finished in | 
|  | ${BMC_SYSLOG_REGEX}      dropbear|vrm-control.sh | 
|  | ${RSYSLOG_REGEX}         start|exiting on signal 15|there are no active actions configured | 
|  | ${RSYSLOG_RETRY_REGEX}   suspended | 
|  | ${valid_password}        0penBmc1 | 
|  | ${max_password_length}   20 | 
|  |  | 
|  | *** Test Cases *** | 
|  |  | 
|  | Test BMC Hostname Service And Verify | 
|  | [Documentation]  Write to hostname interface and verify via REST and | 
|  | ...              'hostname' command. | 
|  | [Tags]  Test_BMC_Hostname_Service_And_Verify | 
|  |  | 
|  | ${openbmc_host_name}  ${openbmc_ip}  ${openbmc_short_name}= | 
|  | ...  Get Host Name IP  host=${OPENBMC_HOST}  short_name=1 | 
|  |  | 
|  | ${host_name_dict}=  Create Dictionary  data=${openbmc_short_name} | 
|  | Write Attribute  ${NETWORK_MANAGER}config  HostName  data=${host_name_dict} | 
|  | ...  verify=${TRUE}  expected_value=${openbmc_short_name} | 
|  |  | 
|  | ${hostname}  ${stderr}  ${rc}=  BMC Execute Command  hostname | 
|  |  | 
|  | Should Be Equal As Strings  ${hostname}  ${openbmc_short_name} | 
|  | ...  msg=The hostname interface ${openbmc_short_name} and command value ${hostname} do not match. | 
|  |  | 
|  | # Override the suite hostname variable if this test is executed. | 
|  | Set Suite Variable  ${bmc_hostname}  ${openbmc_short_name} | 
|  |  | 
|  |  | 
|  | Verify REST Logging On BMC Journal When Disabled | 
|  | [Documentation]  Enable REST logging and verify from journald. | 
|  | [Tags]  Verify_REST_Logging_On_BMC_Journal_When_Disabled | 
|  |  | 
|  | ${log_dict}=  Create Dictionary  data=${False} | 
|  | Write Attribute  ${BMC_LOGGING_URI}${/}rest_api_logs  Enabled  data=${log_dict} | 
|  | ...  verify=${True}  expected_value=${False} | 
|  |  | 
|  | # If it was enabled prior, this REST footprint will show up. | 
|  | # Takes around 5 seconds for the REST to restart service when policy is changed. | 
|  | Sleep  10s | 
|  |  | 
|  | ${login_footprint}=  Catenate  login json: None 200 OK | 
|  | # Example: Just get the message part of the syslog | 
|  | # user:root POST http://xx.xx.xx.xx/login json: None 200 OK | 
|  | ${cmd}=  Catenate  SEPARATOR=  --no-pager | egrep '${login_footprint}' | 
|  |  | 
|  | Start Journal Log  filter=${cmd} | 
|  | Initialize OpenBMC | 
|  | Sleep  5s | 
|  | ${bmc_journald}=  Stop Journal Log | 
|  |  | 
|  | Should Be Empty  ${bmc_journald} | 
|  | ...  msg=${bmc_journald} contains unexpected REST entries. | 
|  |  | 
|  |  | 
|  | Verify REST Logging On BMC Journal When Enabled | 
|  | [Documentation]  Enable REST logging and verify from journald. | 
|  | [Tags]  Verify_REST_Logging_On_BMC_Journal_When_Enabled | 
|  |  | 
|  | ${log_dict}=  Create Dictionary  data=${True} | 
|  | Write Attribute  ${BMC_LOGGING_URI}${/}rest_api_logs  Enabled  data=${log_dict} | 
|  | ...  verify=${True}  expected_value=${True} | 
|  |  | 
|  | Sleep  5s | 
|  |  | 
|  | Start Journal Log | 
|  | Initialize OpenBMC | 
|  | Log Out OpenBMC | 
|  | ${bmc_journald}=  Stop Journal Log | 
|  |  | 
|  | Should Contain  ${bmc_journald}  login json: None 200 OK | 
|  | ...  msg=${bmc_journald} doesn't contains REST entries. | 
|  |  | 
|  |  | 
|  | Test Remote API Valid Config Combination | 
|  | [Documentation]  Verify  valid combination of address and port. | 
|  | [Tags]  Test_Remote_API_Valid_Config_Combination | 
|  | [Template]  Verify Configure Remote Logging Server | 
|  | # Forego normal test setup: | 
|  | [Setup]  No Operation | 
|  |  | 
|  | # Address                    Port                        Expected result | 
|  | ${EMPTY}                     ${REMOTE_LOG_SERVER_PORT}   ${True} | 
|  | ${REMOTE_LOG_SERVER_HOST}    ${REMOTE_LOG_SERVER_PORT}   ${True} | 
|  | ${REMOTE_LOG_SERVER_HOST}    ${0}                        ${True} | 
|  |  | 
|  |  | 
|  | Test Remote API Invalid Config Combination | 
|  | [Documentation]  Verify invalid combination of address and port. | 
|  | [Tags]  Test_Remote_API_Invalid_Config_Combination | 
|  | [Template]  Verify Configure Remote Logging Server | 
|  | # Forego normal test setup: | 
|  | [Setup]  No Operation | 
|  |  | 
|  | # Address                    Port                        Expected result | 
|  | ${0}                         ${REMOTE_LOG_SERVER_PORT}   ${False} | 
|  | "0"                          ${REMOTE_LOG_SERVER_PORT}   ${False} | 
|  | ${REMOTE_LOG_SERVER_HOST}    ${EMPTY}                    ${False} | 
|  | ${REMOTE_LOG_SERVER_HOST}    "0"                         ${False} | 
|  |  | 
|  |  | 
|  | Test Remote Logging REST Interface And Verify Config | 
|  | [Documentation]  Test remote logging interface and configuration. | 
|  | [Tags]  Test_Remote_Logging_REST_Interface_And_Verify_Config | 
|  |  | 
|  | Verify Rsyslog Config On BMC | 
|  |  | 
|  |  | 
|  | Test Remote Logging Invalid Port Config And Verify BMC Journald | 
|  | [Documentation]  Test remote logging interface and configuration. | 
|  | [Tags]  Test_Remote_Logging_Invalid_Port_Config_And_Verify_BMC_Journald | 
|  |  | 
|  | # Invalid port derived by (REMOTE_LOG_SERVER_PORT + 1) port config setting. | 
|  | ${INVALID_PORT}=  Evaluate  ${REMOTE_LOG_SERVER_PORT} + ${1} | 
|  | Configure Remote Log Server With Parameters | 
|  | ...  remote_host=${REMOTE_LOG_SERVER_HOST}  remote_port=${INVALID_PORT} | 
|  |  | 
|  | Sleep  3s | 
|  | # rsyslogd[1870]: action 'action 0' suspended, | 
|  | # next retry is Fri Sep 14 05:47:39 2018 [v8.29.0 try http://www.rsyslog.com/e/2007 ] | 
|  | ${bmc_journald}  ${stderr}  ${rc}=  BMC Execute Command | 
|  | ...  journalctl -b --no-pager | egrep 'rsyslog.*${RSYSLOG_RETRY_REGEX}' | 
|  |  | 
|  | Should Contain  ${bmc_journald}  ${RSYSLOG_RETRY_REGEX} | 
|  | ...  msg=${bmc_journald} doesn't contain rsyslog retry entries. | 
|  |  | 
|  |  | 
|  | Verify BMC Journald Synced To Remote Logging Server | 
|  | [Documentation]  Check that BMC journald is sync to remote rsyslog. | 
|  | [Tags]  Verify_BMC_Journald_Synced_To_Remote_Logging_Server | 
|  |  | 
|  | # Restart BMC dump service and get the last entry of the journald. | 
|  | # Example: | 
|  | # systemd[1]: Started Phosphor Dump Manager. | 
|  | BMC Execute Command | 
|  | ...  systemctl restart xyz.openbmc_project.Dump.Manager.service | 
|  |  | 
|  | ${bmc_journald}  ${stderr}  ${rc}=  BMC Execute Command | 
|  | ...  journalctl --no-pager | grep 'Started Phosphor Dump Manager' | 
|  |  | 
|  | # systemd[1]: Started Phosphor Dump Manager. | 
|  | ${cmd}=  Catenate  SEPARATOR=  egrep '${bmc_hostname}.*Started Phosphor Dump Manager' /var/log/syslog | 
|  | ${remote_journald}=  Remote Logging Server Execute Command  command=${cmd} | 
|  |  | 
|  | # TODO: rsyslog configuration and time date template to match BMC journald. | 
|  | # Compare the BMC journlad log. Example: | 
|  | # systemd[1]: Started Phosphor Dump Manager. | 
|  | Should Contain  ${remote_journald}  ${bmc_journald.split('${bmc_hostname}')[1][0]} | 
|  | ...  msg= ${bmc_journald} doesn't match remote rsyslog:${remote_journald}. | 
|  |  | 
|  |  | 
|  | Verify Journald Post BMC Reset | 
|  | [Documentation]  Check that BMC journald is sync'ed to remote rsyslog after | 
|  | ...              BMC reset. | 
|  | [Tags]  Verify_Journald_Post_BMC_Reset | 
|  |  | 
|  | ${hostname}  ${stderr}  ${rc}=  BMC Execute Command  hostname | 
|  | OBMC Reboot (off) | 
|  |  | 
|  | ${cmd}=  Catenate  grep ${hostname} /var/log/syslog | | 
|  | ...  egrep '${BMC_STOP_MSG}|${BMC_START_MSG}|${BMC_BOOT_MSG}' | 
|  | ${remote_journald}=  Remote Logging Server Execute Command  command=${cmd} | 
|  |  | 
|  | # 1. Last reboot message to verify. | 
|  | Should Contain  ${remote_journald}  ${BMC_STOP_MSG} | 
|  | ...  msg=The remote journald doesn't contain the IPMI shutdown message: ${BMC_STOP_MSG}. | 
|  |  | 
|  | # 2. Earliest booting message on journald. | 
|  | Should Contain  ${remote_journald}  ${BMC_START_MSG} | 
|  | ...  msg=The remote journald doesn't contain the start message: ${BMC_START_MSG}. | 
|  |  | 
|  | # 3. Unique boot to standby message. | 
|  | # Startup finished in 9.961s (kernel) + 1min 59.039s (userspace) = 2min 9.000s | 
|  | ${bmc_journald}  ${stderr}  ${rc}=  BMC Execute Command | 
|  | ...  journalctl -b --no-pager | egrep '${BMC_BOOT_MSG}' | 
|  |  | 
|  | Should Contain  ${remote_journald} | 
|  | ...  ${bmc_journald.split('${hostname}')[1]} | 
|  | ...  msg=The remote journald doesn't contain the boot message: ${BMC_BOOT_MSG}. | 
|  |  | 
|  |  | 
|  | Verify BMC Journald Contains No Credential Data | 
|  | [Documentation]  Check that BMC journald doesn't log any credential data. | 
|  | [Tags]  Verify_BMC_Journald_Contains_No_Credential_Data | 
|  |  | 
|  | Initialize OpenBMC | 
|  |  | 
|  | Create Redfish And IPMI Users | 
|  |  | 
|  | # Time for user manager to sync. | 
|  | Sleep  5 s | 
|  |  | 
|  | Open Connection And Log In | 
|  | ${bmc_journald}  ${stderr}  ${rc}=  BMC Execute Command | 
|  | ...  journalctl -o json-pretty | cat | 
|  |  | 
|  | Should Not Contain Any  ${bmc_journald}  ${OPENBMC_PASSWORD}  ${REST_PASSWORD}  ${valid_password} | 
|  | ...  ignore_case=False  msg=Journald logs BMC credentials/password ${OPENBMC_PASSWORD}. | 
|  |  | 
|  |  | 
|  | Audit BMC SSH Login And Remote Logging | 
|  | [Documentation]  Check that the SSH login to BMC is logged and synced to | 
|  | ...              remote logging server. | 
|  | [Tags]  Audit_BMC_SSH_Login_And_Remote_Logging | 
|  |  | 
|  | ${login_footprint}=  Catenate  Started SSH Per-Connection Server | 
|  | # Example: Just get the message part of the syslog | 
|  | # Started SSH Per-Connection Server (xx.xx.xx.xx:51292) | 
|  | ${cmd}=  Catenate  SEPARATOR=  --no-pager | egrep '${login_footprint}' | 
|  | ...  | awk -F': ' '{print $2}' | 
|  |  | 
|  | Start Journal Log  filter=${cmd} | 
|  | Open Connection And Log In | 
|  | Sleep  5s | 
|  | ${bmc_journald}=  Stop Journal Log | 
|  | @{ssh_entry}=  Split To Lines  ${bmc_journald} | 
|  |  | 
|  | ${cmd}=  Catenate  SEPARATOR=  egrep -E '*${bmc_hostname}.*${login_footprint}' /var/log/syslog | 
|  |  | 
|  | ${remote_journald}=  Remote Logging Server Execute Command  command=${cmd} | 
|  |  | 
|  | Should Contain  ${remote_journald}  ${ssh_entry[0]} | 
|  | ...  msg=${remote_journald} don't contain ${bmc_journald} entry. | 
|  |  | 
|  |  | 
|  | Verify Rsyslog Does Not Log On BMC | 
|  | [Documentation]  Check that rsyslog journald doesn't log on BMC. | 
|  | [Tags]  Verify_Rsyslog_Does_Not_Log_On_BMC | 
|  |  | 
|  | # Expected filter rsyslog entries. | 
|  | # Example: | 
|  | # syslogd[3356]: | 
|  | #   [origin software="rsyslogd" swVersion="8.29.0" x-pid="3356" x-info="http://www.rsyslog.com"] | 
|  | #     exiting on signal 15. | 
|  | # rsyslogd[3364]: | 
|  | # [origin software="rsyslogd" swVersion="8.29.0" x-pid="3364" x-info="http://www.rsyslog.com"] start | 
|  | ${bmc_journald}  ${stderr}  ${rc}=  BMC Execute Command | 
|  | ...  journalctl -b --no-pager | egrep 'rsyslog' | egrep -Ev '${RSYSLOG_REGEX}|${RSYSLOG_RETRY_REGEX}' | 
|  | ...  ignore_err=${1} | 
|  |  | 
|  | Should Be Empty  ${bmc_journald} | 
|  | ...  msg=${bmc_journald} contains unexpected rsyslog entries. | 
|  |  | 
|  |  | 
|  | Boot Host And Verify Data Is Synced To Remote Server | 
|  | [Documentation]  Boot host and verify the power on sequence logs are synced | 
|  | ...              to remote logging server. | 
|  | [Tags]  Boot_Host_And_Verify_Data_Is_Synced_To_Remote_Server | 
|  |  | 
|  | # Filter kernel dmesg from the journald log. | 
|  | # Example: xx.xx.xx kernel: | 
|  |  | 
|  | ${openbmc_host_name}  ${openbmc_ip}  ${openbmc_short_name}= | 
|  | ...  Get Host Name IP  host=${OPENBMC_HOST}  short_name=1 | 
|  |  | 
|  | ${cmd}=  Catenate  SEPARATOR=  --no-pager | egrep -Ev '${BMC_SYSLOG_REGEX} | 
|  | ...  |${openbmc_short_name} kernel' | awk -F': ' '{print $2}' | 
|  |  | 
|  | # Example: Just get the message part of the syslog | 
|  | # Started OpenPOWER OCC Active Disable. | 
|  | Start Journal Log  filter=${cmd} | 
|  |  | 
|  | # Irrespective of the outcome, the journald should be synced. | 
|  | Run Keyword And Ignore Error  Redfish Power On | 
|  | ${bmc_journald}=  Stop Journal Log | 
|  |  | 
|  | ${cmd}=  Catenate  SEPARATOR=  egrep -a '${bmc_hostname}' /var/log/syslog | 
|  | ${remote_journald}=  Remote Logging Server Execute Command  command=${cmd} | 
|  |  | 
|  | @{lines}=  Split To Lines  ${bmc_journald} | 
|  |  | 
|  | FOR  ${line}  IN  @{lines} | 
|  | Log To Console  \n ${line} | 
|  | Should Contain  ${remote_journald}  ${line} | 
|  | ...  mgs=${line} line doesn't contain in ${remote_journald}. | 
|  | END | 
|  |  | 
|  |  | 
|  | *** Keywords *** | 
|  |  | 
|  | Suite Setup Execution | 
|  | [Documentation]  Do the suite setup. | 
|  |  | 
|  | Should Not Be Empty  ${REMOTE_LOG_SERVER_HOST} | 
|  | Should Not Be Empty  ${REMOTE_LOG_SERVER_PORT} | 
|  | Should Not Be Empty  ${REMOTE_USERNAME} | 
|  | Should Not Be Empty  ${REMOTE_PASSWORD} | 
|  | Ping Host  ${REMOTE_LOG_SERVER_HOST} | 
|  | Remote Logging Server Execute Command  true | 
|  | Remote Logging Interface Should Exist | 
|  |  | 
|  | ${hostname}  ${stderr}  ${rc}=  BMC Execute Command  /bin/hostname | 
|  | Set Suite Variable  ${bmc_hostname}  ${hostname} | 
|  | Configure Remote Log Server With Parameters | 
|  |  | 
|  |  | 
|  | Test Setup Execution | 
|  | [Documentation]  Do the test setup. | 
|  |  | 
|  | # Retain only the past 1 second log: | 
|  | BMC Execute Command  journalctl --vacuum-time=1s | 
|  |  | 
|  | ${config_status}=  Run Keyword And Return Status | 
|  | ...  Get Remote Log Server Configured | 
|  |  | 
|  | Run Keyword If  ${config_status}==${FALSE} | 
|  | ...  Configure Remote Log Server With Parameters | 
|  |  | 
|  |  | 
|  | Remote Logging Interface Should Exist | 
|  | [Documentation]  Check that the remote logging URI exist. | 
|  |  | 
|  | ${resp}=  OpenBMC Get Request  ${REMOTE_LOGGING_URI} | 
|  | Should Be Equal As Strings  ${resp.status_code}  ${HTTP_OK} | 
|  |  | 
|  |  | 
|  | Verify Configure Remote Logging Server | 
|  | [Documentation]  Configure the remote logging REST interface on BMC. | 
|  | [Arguments]  ${remote_host}  ${remote_port}  ${expectation} | 
|  |  | 
|  | # Description of argument(s): | 
|  | # remote_host  The host name or IP address of the remote logging server | 
|  | #              (e.g. "xx.xx.xx.xx"). | 
|  | # remote_port  Remote ryslog server port number (e.g. "514"). | 
|  | # expectation  Expect boolean True/False. | 
|  |  | 
|  |  | 
|  | ${status}=  Run Keyword And Return Status | 
|  | ...  Configure Remote Log Server With Parameters  remote_host=${remote_host}  remote_port=${remote_port} | 
|  |  | 
|  | Should Be Equal  ${status}  ${expectation} | 
|  | ...  msg=Test result ${status} and expectation ${expectation} do not match. | 
|  |  | 
|  |  | 
|  | Create Redfish And IPMI Users | 
|  | [Documentation]  Create a valid Redfish and IPMI local user accounts and | 
|  | ...  delete them. | 
|  |  | 
|  | # Create redfish local valid user. | 
|  | ${redfish_username}=  Generate Random String  8  [LETTERS] | 
|  |  | 
|  | Redfish.Login | 
|  |  | 
|  | ${payload}=  Create Dictionary | 
|  | ...  UserName=${redfish_username}  Password=${valid_password} | 
|  | ...  RoleId=Administrator  Enabled=${True} | 
|  | Redfish.Post  /redfish/v1/AccountService/Accounts  body=&{payload} | 
|  | ...  valid_status_codes=[${HTTP_CREATED}] | 
|  |  | 
|  | # Delete newly created user. | 
|  | Redfish.Delete  /redfish/v1/AccountService/Accounts/${redfish_username} | 
|  |  | 
|  | Redfish.Logout | 
|  |  | 
|  | # Create IPMI local valid user. | 
|  | ${random_username}=  Generate Random String  8  [LETTERS] | 
|  | Set Test Variable  ${random_username} | 
|  | ${random_userid}=  Evaluate  random.randint(2, 15)  modules=random | 
|  | IPMI Create User  ${random_userid}  ${random_username} | 
|  |  | 
|  | Run IPMI Standard Command   user set password ${random_userid} ${valid_password} | 
|  |  | 
|  | ${msg}=  Run IPMI Standard Command  user test ${random_userid} ${max_password_length} ${valid_password} | 
|  | Should Contain  ${msg}  Success | 
|  |  | 
|  | # Delete IPMI user. | 
|  | Run IPMI Standard Command  user set name ${random_userid} "" |