Merge "Mtce: Add ActionInfo extension support for reset operations."

This commit is contained in:
Zuul 2022-10-18 15:54:40 +00:00 committed by Gerrit Code Review
commit b88d7456b1
10 changed files with 469 additions and 122 deletions

View File

@ -154,6 +154,7 @@ int bmcUtil_init ( void )
bmcUtil_request_str_array[BMC_THREAD_CMD__POWER_STATUS] = "Query Power Status";
bmcUtil_request_str_array[BMC_THREAD_CMD__RESTART_CAUSE] = "Query Reset Reason";
bmcUtil_request_str_array[BMC_THREAD_CMD__BOOTDEV_PXE] = "Netboot";
bmcUtil_request_str_array[BMC_THREAD_CMD__RAW_GET] = "Raw Get";
bmcUtil_request_str_array[BMC_THREAD_CMD__READ_SENSORS] = "Read Sensors";
bmcUtil_request_str_array[BMC_THREAD_CMD__LAST] = "unknown";
@ -203,6 +204,8 @@ void bmcUtil_info_init ( bmc_info_type & bmc_info )
bmc_info.power_ctrl.poweron.immediate = "" ;
bmc_info.power_ctrl.poweroff.graceful = "" ;
bmc_info.power_ctrl.poweroff.immediate = "" ;
bmc_info.power_ctrl.raw_target_path = "" ;
}
/*************************************************************************

View File

@ -38,6 +38,8 @@ typedef struct
typedef struct
{
/* Set to next level url to query if required */
string raw_target_path ;
bmc_power_ctrl_type reset ;
bmc_power_ctrl_type poweron ;
bmc_power_ctrl_type poweroff ;
@ -101,6 +103,7 @@ typedef enum
BMC_THREAD_CMD__POWER_OFF,
BMC_THREAD_CMD__POWER_CYCLE,
BMC_THREAD_CMD__RAW_GET,
BMC_THREAD_CMD__BMC_INFO,
BMC_THREAD_CMD__POWER_STATUS,
BMC_THREAD_CMD__RESTART_CAUSE,
@ -114,6 +117,7 @@ typedef enum
#define BMC_QUERY_FILE_SUFFIX ((const char *)("_root_query"))
#define BMC_INFO_FILE_SUFFIX ((const char *)("_bmc_info"))
#define BMC_RAW_GET_FILE_SUFFIX ((const char *)("_raw_get"))
#define BMC_POWER_CMD_FILE_SUFFIX ((const char *)("_power_cmd_result"))
#define BMC_RESET_CMD_FILE_SUFFIX ((const char *)("_reset"))
#define BMC_BOOTDEV_CMD_FILE_SUFFIX ((const char *)("_bootdev"))

View File

@ -108,7 +108,7 @@ static struct json_object * _json_verify_object ( struct json_object * obj,
{
return (req_obj);
}
wlog ("Specified label '%s' not found in response\n", label );
jlog ("Specified label '%s' not found in response\n", label );
status = json_object_object_get_ex (obj, "error", &req_obj );
if (( status == true ) && ( req_obj ))
{

View File

@ -78,7 +78,7 @@ int redfishUtil_init ( void )
/*************************************************************************
*
* Name : _load_action_lists
* Name : redfishUtil_load_actions
*
* Purpose : Load supported host actions.
*
@ -92,9 +92,9 @@ int redfishUtil_init ( void )
*
*************************************************************************/
void _load_action_lists ( string & hostname,
bmc_info_type & bmc_info,
std::list<string> & host_action_list)
void redfishUtil_load_actions ( string & hostname,
bmc_info_type & bmc_info,
std::list<string> & host_action_list)
{
/* Walk through the host action list looking for and updating
* this host's bmc_info supported actions lists */
@ -131,7 +131,7 @@ void _load_action_lists ( string & hostname,
if (( bmc_info.power_ctrl.reset.graceful.empty() ) &&
( bmc_info.power_ctrl.reset.immediate.empty() ))
{
elog("%s bmc offers no 'Reset' commands (%s:%s)",
wlog("%s bmc offers no 'Reset' commands (%s:%s)",
hostname.c_str(),
REDFISHTOOL_RESET__GRACEFUL_RESTART,
REDFISHTOOL_RESET__FORCE_RESTART);
@ -156,7 +156,7 @@ void _load_action_lists ( string & hostname,
if (( bmc_info.power_ctrl.poweron.graceful.empty() ) &&
( bmc_info.power_ctrl.poweron.immediate.empty() ))
{
elog("%s bmc offers no 'Power-On' commands (%s:%s)",
wlog("%s bmc offers no 'Power-On' commands (%s:%s)",
hostname.c_str(),
REDFISHTOOL_POWER_ON__ON,
REDFISHTOOL_POWER_ON__FORCE_ON);
@ -181,7 +181,7 @@ void _load_action_lists ( string & hostname,
if (( bmc_info.power_ctrl.poweroff.graceful.empty() ) &&
( bmc_info.power_ctrl.poweroff.immediate.empty() ))
{
elog("%s bmc offers no 'Power-Off' commands (%s:%s)",
wlog("%s bmc offers no 'Power-Off' commands (%s:%s)",
hostname.c_str(),
REDFISHTOOL_POWER_OFF__GRACEFUL_SHUTDOWN,
REDFISHTOOL_POWER_OFF__FORCE_OFF);
@ -548,22 +548,77 @@ int redfishUtil_get_bmc_info ( string & hostname,
std::list<string> action_list ;
/* get the first level reset action label content */
string json_actions =
jsonUtil_get_key_value_string (json_obj_actions,
REDFISHTOOL_RESET_ACTIONS_LABEL);
if ( jsonUtil_get_list ((char*)json_actions.data(), REDFISHTOOL_RESET_ACTIONS_ALLOWED_LABEL, action_list ) == PASS )
string json_actions = jsonUtil_get_key_value_string (json_obj_actions,
REDFISH_LABEL__ACTION_RESET);
if ( !json_actions.empty() && json_actions.compare("none") )
{
_load_action_lists ( hostname, bmc_info, action_list);
if ( jsonUtil_get_list ((char*)json_actions.data(),
REDFISH_LABEL__ACTION_RESET_ALLOWED,
action_list ) == PASS )
{
redfishUtil_load_actions ( hostname, bmc_info, action_list);
}
else
{
/************************************************************
* If the REDFISH_LABEL__ACTION_RESET does not contain
* the REDFISH_LABEL__ACTION_RESET_ALLOWED then tell the
* bmc_handler FSM to query the action list through the
* REDFISH_LABEL__ACTION_INFO key value target saved to
* the bmc_info.power_ctrl.raw_target_path.
************************************************************/
blog ("%s bmc not offering action list through %s",
hostname.c_str(),
REDFISH_LABEL__ACTION_RESET_ALLOWED );
struct json_object *json_actions_obj =
json_tokener_parse((char*)json_actions.data());
if ( json_actions_obj )
{
string json_actions_target =
jsonUtil_get_key_value_string(json_actions_obj,
REDFISH_LABEL__ACTION_INFO);
if ( !json_actions_target.empty() && json_actions_target.compare("none") )
{
blog ("%s posting %s target %s to bmc handler",
hostname.c_str(),
REDFISH_LABEL__ACTION_INFO,
json_actions_target.c_str());
/* Post the target to the bmc handler to query
* using redfishtool raw GET mode */
bmc_info.power_ctrl.raw_target_path = json_actions_target ;
}
else
{
wlog ("%s failed to get %s target",
hostname.c_str(),
REDFISH_LABEL__ACTION_INFO);
return ( FAIL_STRING_EMPTY );
}
}
else
{
wlog ("%s null json object from %s using label %s",
hostname.c_str(),
json_actions.c_str(),
REDFISH_LABEL__ACTION_RESET_ALLOWED);
return ( FAIL_JSON_PARSE );
}
}
}
else
{
elog ("%s actions list get failed ; [%s]", hostname.c_str(), json_actions.c_str());
wlog ("%s failed parse string from %s object",
hostname.c_str(),
REDFISH_LABEL__ACTION_RESET );
return ( FAIL_JSON_PARSE );
}
}
else
{
elog ("%s action object get failed", hostname.c_str());
wlog ("%s action object get failed", hostname.c_str());
return ( FAIL_JSON_PARSE );
}
/* get number of processors */

View File

@ -46,6 +46,16 @@ typedef struct
} redfish_entity_status ;
/*
*
* Redfish Data Model Specification:
* https://www.dmtf.org/sites/default/files/standards/documents/DSP0268_2022.2.pdf
*
* Redfish Resource and Schema Guide:
* https://www.dmtf.org/sites/default/files/standards/documents/DSP2046_2022.2.pdf
*
*/
/* Redfish version format is #.#.# or major.minor.revision
* This feature does not care about revision.
* The following are the minimum version numbers for major and minor
@ -76,25 +86,14 @@ typedef struct
#define REDFISHTOOL_BMC_INFO_CMD ((const char *)("Systems get"))
/* supported actions */
#define REDFISH_LABEL__ACTIONS ((const char *)("Actions"))
#define REDFISH_LABEL__ACTION_RESET ((const char *)("#ComputerSystem.Reset"))
#define REDFISH_LABEL__ACTION_RESET_ALLOWED ((const char *)("ResetType@Redfish.AllowableValues"))
/*********** supported reset/power command actions queries **************
/* Redfish Reset Types:
*
* https://www.dmtf.org/sites/default/files/standards/documents/DSP0268_2019.1a.pdf */
Method 1: Single level query through root query 'Actions'
#define REDFISHTOOL_POWER_RESET_CMD ((const char *)("Systems reset "))
#ComputerSystem.Reset
ResetType@Redfish.AllowableValues [list]
typedef enum
{
REDFISH_ACTION__RESET,
REDFISH_ACTION__POWER_ON,
REDFISH_ACTION__POWER_OFF,
} redfish_action_enum ;
/* Reset actions allows json block
Method 1: payload response ( level 1 )
"Actions": {
"#ComputerSystem.Reset": {
@ -109,10 +108,70 @@ typedef enum
}
},
*/
#define REDFISHTOOL_RESET_ACTIONS_LABEL ((const char *)("#ComputerSystem.Reset")) /* level 1 label */
#define REDFISHTOOL_RESET_ACTIONS_ALLOWED_LABEL ((const char *)("ResetType@Redfish.AllowableValues")) /* level 2 label */
-----or-----
Method 2: Double level query through root query 'Actions'
#ComputerSystem.Reset
@Redfish.ActionInfo -> /redfish/v1/Systems/1/ResetActionInfo
arameters
AllowableValues [list]
Method 2 level 1 payload response
"Actions": {
"#ComputerSystem.Reset": {
"target": "/redfish/v1/Systems/1/Actions/ComputerSystem.Reset",
"@Redfish.ActionInfo": "/redfish/v1/Systems/1/ResetActionInfo"
}
},
Method 2 level 2 payload response through @Redfish.ActionInfo target
GET: /redfish/v1/Systems/1/ResetActionInfo
"@odata.type": "#ActionInfo.v1_1_2.ActionInfo",
"Name": "Reset Action Info",
"Parameters": [
{
"DataType": "String",
"AllowableValues": [
"On",
"ForceOff",
"GracefulShutdown",
"GracefulRestart",
"ForceRestart",
"Nmi",
"ForceOn"
],
"Required": true,
"Name": "ResetType"
}
],
"@odata.id": "/redfish/v1/Systems/1/ResetActionInfo",
"Oem": {},
"Id": "ResetActionInfo"
} */
/* First level reset/power control GET labels */
#define REDFISH_LABEL__ACTIONS ((const char *)("Actions")) /* level 0 */
#define REDFISH_LABEL__ACTION_RESET ((const char *)("#ComputerSystem.Reset")) /* level 1 */
#define REDFISH_LABEL__ACTION_RESET_ALLOWED ((const char *)("ResetType@Redfish.AllowableValues")) /* level 2 */
/* Second level reset/power control GET labels */
#define REDFISH_LABEL__ACTION_INFO ((const char *)("@Redfish.ActionInfo"))
#define REDFISH_LABEL__PARAMETERS ((const char *)("Parameters"))
#define REDFISH_LABEL__ALLOWABLE_VALUES ((const char *)("AllowableValues"))
#define REDFISHTOOL_RAW_GET_CMD ((const char *)("raw GET "))
#define REDFISHTOOL_POWER_RESET_CMD ((const char *)("Systems reset "))
typedef enum
{
REDFISH_ACTION__RESET,
REDFISH_ACTION__POWER_ON,
REDFISH_ACTION__POWER_OFF,
} redfish_action_enum ;
/* Reset sub-commands */
#define REDFISHTOOL_RESET__GRACEFUL_RESTART ((const char *)("GracefulRestart")) /* Perform a graceful shutdown followed by a restart of the system. */
@ -164,5 +223,10 @@ int redfishUtil_get_bmc_info ( string & hostname,
bmc_info_type & bmc_info );
string redfishUtil_get_cmd_option ( redfish_action_enum action,
std::list<string> host_action_list );
std::list<string> host_action_list );
void redfishUtil_load_actions ( string & hostname,
bmc_info_type & bmc_info,
std::list<string> & host_action_list);
#endif // __INCLUDE_REDFISHUTIL_H__

View File

@ -4414,6 +4414,38 @@ void nodeLinkClass::bmc_load_protocol ( struct nodeLinkClass::node * node_ptr )
mtcInvApi_update_mtcInfo ( node_ptr );
}
/* Default the bmc handler query control variables */
void nodeLinkClass::bmc_default_query_controls ( struct nodeLinkClass::node * node_ptr )
{
node_ptr->bmc_info_query_active = false ;
node_ptr->bmc_info_query_done = false ;
node_ptr->reset_cause_query_active = false ;
node_ptr->reset_cause_query_done = false ;
node_ptr->power_status_query_active = false ;
node_ptr->power_status_query_done = false ;
node_ptr->bmc_actions_query_active = false ;
node_ptr->bmc_actions_query_done = false ;
}
/* Force bmc access protocol to IPMI */
int nodeLinkClass::bmc_default_to_ipmi ( struct nodeLinkClass::node * node_ptr )
{
ilog ("%s defaulting to ipmi", node_ptr->hostname.c_str());
/* reset all control variables */
bmc_default_query_controls ( node_ptr );
node_ptr->bmc_protocol_learning = false ;
node_ptr->bmc_protocol = BMC_PROTOCOL__IPMITOOL ;
mtcInfo_set ( node_ptr, MTCE_INFO_KEY__BMC_PROTOCOL, BMC_PROTOCOL__IPMI_STR );
mtcInvApi_update_mtcInfo ( node_ptr );
return (PASS);
}
void nodeLinkClass::bmc_access_data_init ( struct nodeLinkClass::node * node_ptr )
{
if ( node_ptr )
@ -4421,12 +4453,9 @@ void nodeLinkClass::bmc_access_data_init ( struct nodeLinkClass::node * node_ptr
node_ptr->bm_pw.clear();
node_ptr->bmc_accessible = false ;
node_ptr->bm_ping_info.ok = false ;
node_ptr->bmc_info_query_active = false ;
node_ptr->bmc_info_query_done = false ;
node_ptr->reset_cause_query_active = false ;
node_ptr->reset_cause_query_done = false ;
node_ptr->power_status_query_active = false ;
node_ptr->power_status_query_done = false ;
/* default bmc handler query controlo variables */
bmc_default_query_controls ( node_ptr );
node_ptr->bm_ping_info.stage = PINGUTIL_MONITOR_STAGE__OPEN ;
mtcTimer_reset ( node_ptr->bm_ping_info.timer );

View File

@ -689,6 +689,10 @@ private:
bool power_status_query_active ;
bool power_status_query_done ;
bool bmc_actions_query_active ;
bool bmc_actions_query_done ;
bool power_on = false ;
/* a timer used in the bmc_handler to query
@ -1160,6 +1164,8 @@ private:
int set_bm_prov ( struct nodeLinkClass::node * node_ptr, bool state );
void bmc_load_protocol ( struct nodeLinkClass::node * node_ptr );
void bmc_default_query_controls ( struct nodeLinkClass::node * node_ptr );
int bmc_default_to_ipmi ( struct nodeLinkClass::node * node_ptr );
void set_uptime ( struct nodeLinkClass::node * node_ptr, unsigned int uptime, bool force );

View File

@ -76,11 +76,28 @@ int nodeLinkClass::bmc_command_send ( struct nodeLinkClass::node * node_ptr,
if ( node_ptr->bmc_thread_info.proto == BMC_PROTOCOL__REDFISHTOOL )
{
node_ptr->bm_cmd = REDFISHTOOL_POWER_RESET_CMD ;
/* set the command specific redfishtool base command string */
if ( command == BMC_THREAD_CMD__RAW_GET )
node_ptr->bm_cmd = REDFISHTOOL_RAW_GET_CMD ;
else
node_ptr->bm_cmd = REDFISHTOOL_POWER_RESET_CMD ;
/* build the reset/power control command */
/* append to the reset/power control or raw get command string */
switch (command)
{
case BMC_THREAD_CMD__RAW_GET:
{
if ( ! node_ptr->bmc_info.power_ctrl.raw_target_path.empty() )
{
node_ptr->bm_cmd.append(node_ptr->bmc_info.power_ctrl.raw_target_path);
}
else
{
elog("%s is missing the raw get target", node_ptr->hostname.c_str());
return(FAIL_NOT_SUPPORTED);
}
break ;
}
case BMC_THREAD_CMD__POWER_RESET:
{
/* use immediate for all retries if server supports an immediate command */
@ -457,13 +474,15 @@ bmc_command_recv_cleanup:
if ( rc != RETRY )
{
ilog ("%s %s recv '%s' command (%s) (rc:%d)",
node_ptr->hostname.c_str(),
node_ptr->bmc_thread_ctrl.name.c_str(),
bmcUtil_getCmd_str(node_ptr->bmc_thread_info.command).c_str(),
bmcUtil_getProtocol_str(node_ptr->bmc_protocol).c_str(),
rc);
if ( rc != PASS )
{
ilog ("%s %s recv '%s' command (%s) (rc:%d)",
node_ptr->hostname.c_str(),
node_ptr->bmc_thread_ctrl.name.c_str(),
bmcUtil_getCmd_str(node_ptr->bmc_thread_info.command).c_str(),
bmcUtil_getProtocol_str(node_ptr->bmc_protocol).c_str(),
rc);
}
node_ptr->bmc_thread_ctrl.done = true ;
node_ptr->bmc_thread_ctrl.retries = 0 ;
node_ptr->bmc_thread_ctrl.id = 0 ;

View File

@ -6578,13 +6578,10 @@ int nodeLinkClass::bmc_handler ( struct nodeLinkClass::node * node_ptr )
/* send the BMC Query request ; redfish 'root' request */
if ( bmc_command_send ( node_ptr, BMC_THREAD_CMD__BMC_QUERY ) != PASS )
{
wlog ("%s %s send failed ; defaulting to ipmi",
wlog ("%s %s send failed",
node_ptr->hostname.c_str(),
bmcUtil_getCmd_str(node_ptr->bmc_thread_info.command).c_str());
node_ptr->bmc_protocol_learning = false ;
node_ptr->bmc_protocol = BMC_PROTOCOL__IPMITOOL ;
mtcInfo_set ( node_ptr, MTCE_INFO_KEY__BMC_PROTOCOL, BMC_PROTOCOL__IPMI_STR );
mtcInvApi_update_mtcInfo ( node_ptr );
return ( bmc_default_to_ipmi ( node_ptr ) );
}
else
{
@ -6613,26 +6610,21 @@ int nodeLinkClass::bmc_handler ( struct nodeLinkClass::node * node_ptr )
if (( node_ptr->bmc_thread_info.command == BMC_THREAD_CMD__BMC_QUERY ) &&
(( rc == FAIL_SYSTEM_CALL ) || ( rc == FAIL_NOT_ACTIVE )))
{
ilog("%s BMC REe-Connect End ; ipmi", node_ptr->hostname.c_str());
ilog("%s BMC Re-Connect End ; ipmi", node_ptr->hostname.c_str());
/* TODO: may need retries */
plog ("%s bmc does not support Redfish ; " \
"defaulting to ipmi",
plog ("%s bmc does not support Redfish",
node_ptr->hostname.c_str());
}
else
{
wlog ("%s %s recv failed (rc:%d:%d:%s); defaulting to ipmi",
wlog ("%s %s recv failed (rc:%d:%d:%s)",
node_ptr->hostname.c_str(),
bmcUtil_getCmd_str(node_ptr->bmc_thread_info.command).c_str(),
rc,
node_ptr->bmc_thread_info.status,
node_ptr->bmc_thread_info.status_string.c_str());
node_ptr->bmc_thread_info.status_string.c_str());
}
node_ptr->bmc_protocol = BMC_PROTOCOL__IPMITOOL ;
mtcInfo_set ( node_ptr, MTCE_INFO_KEY__BMC_PROTOCOL, BMC_PROTOCOL__IPMI_STR );
mtcInvApi_update_mtcInfo ( node_ptr );
node_ptr->bmc_protocol_learning = false ;
node_ptr->bmc_thread_ctrl.done = true ;
return ( bmc_default_to_ipmi ( node_ptr ) );
}
else
{
@ -6691,9 +6683,10 @@ int nodeLinkClass::bmc_handler ( struct nodeLinkClass::node * node_ptr )
node_ptr->hostname.c_str(),
bmcUtil_getCmd_str(
node_ptr->bmc_thread_info.command).c_str());
node_ptr->bmc_protocol = BMC_PROTOCOL__IPMITOOL ;
mtcInfo_set ( node_ptr, MTCE_INFO_KEY__BMC_PROTOCOL, BMC_PROTOCOL__IPMI_STR );
mtcInvApi_update_mtcInfo ( node_ptr );
if ( node_ptr->bmc_protocol_learning )
{
return ( bmc_default_to_ipmi ( node_ptr ) );
}
}
else
{
@ -6704,7 +6697,7 @@ int nodeLinkClass::bmc_handler ( struct nodeLinkClass::node * node_ptr )
mtcTimer_start ( node_ptr->bm_timer, mtcTimer_handler, MTC_FIRST_WAIT );
}
}
else if ( node_ptr->bmc_info_query_active == true )
else
{
int rc ;
if ( ( rc = bmc_command_recv ( node_ptr ) ) == RETRY )
@ -6713,10 +6706,16 @@ int nodeLinkClass::bmc_handler ( struct nodeLinkClass::node * node_ptr )
}
else if ( rc != PASS )
{
/* this error is reported by the receive driver */
node_ptr->bmc_info_query_active = false ;
node_ptr->bmc_thread_ctrl.done = true ;
mtcTimer_start ( node_ptr->bm_timer, mtcTimer_handler, MTC_BMC_REQUEST_DELAY );
if ( node_ptr->bmc_protocol_learning )
bmc_default_to_ipmi ( node_ptr );
else
{
/* If not in learning mode then force the retry
* from start in MTC_BMC_REQUEST_DELAY seconds */
bmc_default_query_controls ( node_ptr );
node_ptr->bmc_thread_ctrl.done = true ;
mtcTimer_start ( node_ptr->bm_timer, mtcTimer_handler, MTC_BMC_REQUEST_DELAY );
}
}
else
{
@ -6728,67 +6727,229 @@ int nodeLinkClass::bmc_handler ( struct nodeLinkClass::node * node_ptr )
node_ptr->bmc_thread_info.data,
node_ptr->bmc_info ) != PASS )
{
elog ("%s bmc %s failed ; defaulting to ipmi",
elog ("%s bmc redfish %s or get bmc info failed",
node_ptr->hostname.c_str(),
bmcUtil_getCmd_str(
node_ptr->bmc_thread_info.command).c_str());
node_ptr->bmc_info_query_active = false ;
node_ptr->bmc_info_query_done = false ;
node_ptr->bmc_protocol = BMC_PROTOCOL__IPMITOOL ;
mtcInfo_set ( node_ptr, MTCE_INFO_KEY__BMC_PROTOCOL, BMC_PROTOCOL__IPMI_STR );
if ( node_ptr->bmc_protocol_learning )
bmc_default_to_ipmi ( node_ptr );
else
{
/* If not in learning mode then force the retry
* from start in MTC_BMC_REQUEST_DELAY seconds */
bmc_default_query_controls ( node_ptr );
mtcTimer_start ( node_ptr->bm_timer, mtcTimer_handler, MTC_BMC_REQUEST_DELAY );
}
}
else
{
mtcTimer_reset ( node_ptr->bm_timer );
mtcTimer_reset ( node_ptr->bmc_audit_timer );
int bmc_audit_period = daemon_get_cfg_ptr()->bmc_audit_period ;
if ( bmc_audit_period )
{
/* the time for the first audit is twice the configured period */
mtcTimer_start ( node_ptr->bmc_audit_timer, mtcTimer_handler, bmc_audit_period*2 );
plog ("%s bmc audit timer started (%d secs)", node_ptr->hostname.c_str(), bmc_audit_period*2);
}
else
{
ilog("%s bmc audit disabled", node_ptr->hostname.c_str());
}
/* success path */
node_ptr->bmc_accessible = true ;
node_ptr->bmc_info_query_done = true ;
node_ptr->bmc_info_query_active = false ;
node_ptr->bmc_protocol_learning = false ;
mtcInfo_set ( node_ptr, MTCE_INFO_KEY__BMC_PROTOCOL, BMC_PROTOCOL__REDFISH_STR );
mtcTimer_reset ( node_ptr->bmc_access_timer );
/* save the host's power state */
node_ptr->power_on = node_ptr->bmc_info.power_on ;
plog ("%s bmc is accessible using redfish",
node_ptr->hostname.c_str());
node_ptr->bmc_thread_ctrl.done = true ;
node_ptr->bmc_thread_info.command = 0 ;
}
/* store mtcInfo, which specifies the selected BMC protocol,
* into the sysinv database */
mtcInvApi_update_mtcInfo ( node_ptr );
/* push the BMC access info out to the mtcClient when
* a controller's BMC connection is established/verified */
if ( node_ptr->nodetype & CONTROLLER_TYPE )
this->want_mtcInfo_push = true ;
send_hwmon_command ( node_ptr->hostname, MTC_CMD_ADD_HOST );
send_hwmon_command ( node_ptr->hostname, MTC_CMD_START_HOST );
}
}
}
/* Handle Redfish BMC reset/power command query using the redfishtool
* raw GET command.
* This is the last operation before declaring the BMC accessible */
else if (( node_ptr->bmc_protocol == BMC_PROTOCOL__REDFISHTOOL ) &&
( node_ptr->bmc_accessible == false ) &&
( node_ptr->bm_ping_info.ok == true ) &&
( node_ptr->bmc_info_query_done == true ) &&
( node_ptr->bmc_actions_query_done == false ) &&
( mtcTimer_expired (node_ptr->bm_timer ) == true ))
{
if ( node_ptr->bmc_info.power_ctrl.raw_target_path.empty() )
{
node_ptr->bmc_actions_query_done = true ;
}
else if ( node_ptr->bmc_actions_query_active == false )
{
blog ("%s bmc action info target: %s",
node_ptr->hostname.c_str(),
node_ptr->bmc_info.power_ctrl.raw_target_path.c_str());
if ( bmc_command_send ( node_ptr, BMC_THREAD_CMD__RAW_GET ) != PASS )
{
elog ("%s bmc redfish '%s' send failed\n",
node_ptr->hostname.c_str(),
bmcUtil_getCmd_str(
node_ptr->bmc_thread_info.command).c_str());
if ( node_ptr->bmc_protocol_learning )
bmc_default_to_ipmi ( node_ptr );
else
{
/* If not in learning mode then force the retry
* from start in MTC_BMC_REQUEST_DELAY seconds */
bmc_default_query_controls ( node_ptr );
mtcTimer_start ( node_ptr->bm_timer, mtcTimer_handler, MTC_BMC_REQUEST_DELAY );
}
}
else
{
node_ptr->bmc_actions_query_active = true ;
blog ("%s bmc redfish '%s' in progress",
node_ptr->hostname.c_str(),
bmcUtil_getCmd_str(node_ptr->bmc_thread_info.command).c_str());
mtcTimer_start ( node_ptr->bm_timer, mtcTimer_handler, MTC_FIRST_WAIT );
}
}
else
{
int rc ;
bool default_to_ipmi = false ;
if ( ( rc = bmc_command_recv ( node_ptr ) ) == RETRY )
{
mtcTimer_start ( node_ptr->bm_timer, mtcTimer_handler, MTC_RETRY_WAIT );
}
else if ( rc != PASS )
{
if ( node_ptr->bmc_protocol_learning )
bmc_default_to_ipmi ( node_ptr );
else
{
/* If not in learning mode then force the retry
* from start in MTC_BMC_REQUEST_DELAY seconds */
bmc_default_query_controls ( node_ptr );
node_ptr->bmc_thread_ctrl.done = true ;
mtcTimer_start ( node_ptr->bm_timer, mtcTimer_handler, MTC_BMC_REQUEST_DELAY );
}
}
else
{
node_ptr->bmc_thread_ctrl.done = true ;
blog ("%s bmc thread info cmd: %s data:\n%s",
node_ptr->hostname.c_str(),
bmcUtil_getCmd_str(
node_ptr->bmc_thread_info.command).c_str(),
node_ptr->bmc_thread_info.data.c_str() );
/* Look for Parameters as list */
std::list<string> param_list ;
if ( jsonUtil_get_list ((char*)node_ptr->bmc_thread_info.data.data(),
REDFISH_LABEL__PARAMETERS,
param_list ) == PASS )
{
/* Walk through the host action list looking for and updating
* this host's bmc_info supported actions lists */
int index = 0 ;
bool actions_found = false ;
std::list<string>::iterator param_list_ptr ;
for ( param_list_ptr = param_list.begin();
param_list_ptr != param_list.end() ;
param_list_ptr++, ++index )
{
std::list<string> action_list ;
string param_list_str = *param_list_ptr ;
blog ("%s %s element %d:%s",
node_ptr->hostname.c_str(),
REDFISH_LABEL__PARAMETERS,
index, param_list_str.c_str());
if ( jsonUtil_get_list ((char*)param_list_str.data(),
REDFISH_LABEL__ALLOWABLE_VALUES,
action_list ) == PASS )
{
actions_found = true ;
redfishUtil_load_actions ( node_ptr->hostname,
node_ptr->bmc_info,
action_list );
break ;
}
}
if ( actions_found == false )
{
elog ("%s failed to find '%s' in:\n%s",
node_ptr->hostname.c_str(),
REDFISH_LABEL__ALLOWABLE_VALUES,
node_ptr->bmc_thread_info.data.c_str());
default_to_ipmi = true ;
}
}
else
{
elog ("%s failed to get Action '%s' list from %s",
node_ptr->hostname.c_str(),
REDFISH_LABEL__PARAMETERS,
node_ptr->bmc_thread_info.data.c_str());
default_to_ipmi = true ;
}
/* force failover to use IPMI */
if ( default_to_ipmi == true )
{
if ( node_ptr->bmc_protocol_learning )
bmc_default_to_ipmi ( node_ptr );
else
{
bmc_default_query_controls ( node_ptr );
node_ptr->bmc_thread_ctrl.done = true ;
mtcTimer_start ( node_ptr->bm_timer, mtcTimer_handler, MTC_BMC_REQUEST_DELAY );
}
}
else
{
node_ptr->bmc_actions_query_done = true ;
node_ptr->bmc_actions_query_active = false ;
}
}
}
/* finish up when the actions query is done */
if ( node_ptr->bmc_actions_query_done == true )
{
mtcTimer_reset ( node_ptr->bm_timer );
mtcTimer_reset ( node_ptr->bmc_audit_timer );
int bmc_audit_period = daemon_get_cfg_ptr()->bmc_audit_period ;
if ( bmc_audit_period )
{
/* the time for the first audit is twice the configured period */
mtcTimer_start ( node_ptr->bmc_audit_timer, mtcTimer_handler, bmc_audit_period*2 );
plog ("%s bmc audit timer started (%d secs)", node_ptr->hostname.c_str(), bmc_audit_period*2);
}
else
{
ilog("%s bmc audit disabled", node_ptr->hostname.c_str());
}
/* success path */
node_ptr->bmc_accessible = true ;
node_ptr->bmc_info_query_done = true ;
node_ptr->bmc_info_query_active = false ;
node_ptr->bmc_actions_query_done = true ;
node_ptr->bmc_actions_query_active = false ;
node_ptr->bmc_protocol_learning = false ;
mtcInfo_set ( node_ptr, MTCE_INFO_KEY__BMC_PROTOCOL, BMC_PROTOCOL__REDFISH_STR );
mtcTimer_reset ( node_ptr->bmc_access_timer );
/* save the host's power state */
node_ptr->power_on = node_ptr->bmc_info.power_on ;
plog ("%s bmc is accessible using redfish",
node_ptr->hostname.c_str());
node_ptr->bmc_thread_ctrl.done = true ;
node_ptr->bmc_thread_info.command = 0 ;
/* store mtcInfo, which specifies the selected BMC protocol,
* into the sysinv database */
mtcInvApi_update_mtcInfo ( node_ptr );
/* push the BMC access info out to the mtcClient when
* a controller's BMC connection is established/verified */
if ( node_ptr->nodetype & CONTROLLER_TYPE )
this->want_mtcInfo_push = true ;
send_hwmon_command ( node_ptr->hostname, MTC_CMD_ADD_HOST );
send_hwmon_command ( node_ptr->hostname, MTC_CMD_START_HOST );
}
}
/*****************************************************************
* Handle IPMI BMC Info Query
*

View File

@ -109,6 +109,12 @@ void * mtcThread_bmc ( void * arg )
suffix = BMC_QUERY_FILE_SUFFIX ;
break ;
}
case BMC_THREAD_CMD__RAW_GET:
{
command = extra_ptr->bm_cmd ;
suffix = BMC_RAW_GET_FILE_SUFFIX ;
break ;
}
case BMC_THREAD_CMD__BMC_INFO:
case BMC_THREAD_CMD__POWER_STATUS:
{