From: Anand Sundararaj <s.an...@gethighavailability.com> --- src/amf/amfnd/amfnd.cc | 28 ++++-- src/amf/amfnd/avnd_cb.h | 2 + src/amf/amfnd/avnd_comp.h | 2 + src/amf/amfnd/clm.cc | 47 +++++++-- src/amf/amfnd/err.cc | 31 +++++- src/amf/amfnd/imm.cc | 238 +++++++++++++++++++++++++++++++++++++++------- 6 files changed, 296 insertions(+), 52 deletions(-)
diff --git a/src/amf/amfnd/amfnd.cc b/src/amf/amfnd/amfnd.cc index 1bf057d..7b7a1ae 100644 --- a/src/amf/amfnd/amfnd.cc +++ b/src/amf/amfnd/amfnd.cc @@ -27,7 +27,6 @@ #include <cinttypes> #include "amf/amfnd/avnd.h" - // Remember MDS install version of Agents. It can be used to send msg to Agent // based on their versions. std::map<MDS_DEST, MDS_SVC_PVT_SUB_PART_VER> agent_mds_ver_db; @@ -203,12 +202,18 @@ uint32_t avnd_evt_avnd_avnd_api_resp_msg_hdl(AVND_CB *cb, AVND_EVT *evt) { AVND_COMP *o_comp = m_AVND_INT_EXT_COMPDB_REC_GET(cb->internode_avail_comp_db, comp_name); if (nullptr == o_comp) { - LOG_ER("Couldn't find comp in Inter/Ext Comp DB"); - res = NCSCC_RC_FAILURE; - goto done; + TRACE("Couldn't find comp in Inter/Ext Comp DB"); + // Check if it is a internode responses like error report, etc. + o_comp = avnd_cb->compdb_internode.find(comp_name); + if (nullptr == o_comp) { + LOG_ER("Couldn't find comp in internode comp DB"); + res = NCSCC_RC_FAILURE; + goto done; + } else { + TRACE("Comp '%s' found in internode comp DB", o_comp->name.c_str()); + } } reg_dest = o_comp->reg_dest; - /***************************************************************************** * Some processing for registration and unregistration starts *****************************************************************************/ @@ -275,9 +280,14 @@ uint32_t avnd_evt_avnd_avnd_api_resp_msg_hdl(AVND_CB *cb, AVND_EVT *evt) { /* We have to fprwrd this message to AvA. */ res = avnd_amf_resp_send(cb, resp_info->type, resp_info->rc, - (uint8_t *)ha_state, ®_dest, &avnd_msg->mds_ctxt, + reinterpret_cast<uint8_t *>(ha_state), + &o_comp->reg_dest, &avnd_msg->mds_ctxt, nullptr, false); - + if (o_comp->comp_type == AVND_COMP_TYPE_INTER_NODE_NP) { + TRACE("Comp '%s' deleted from internode comp DB", o_comp->name.c_str()); + cb->compdb_internode.erase(o_comp->name); + delete o_comp; + } if (NCSCC_RC_SUCCESS != res) { LOG_ER("%s: Msg Send to AvA Failed:Comp:%s ,Type: %u, rc:%u, Dest:%" PRIu64, __FUNCTION__, comp_name.c_str(), resp_info->type, resp_info->rc, @@ -384,8 +394,8 @@ done: if (NCSCC_RC_SUCCESS != rc) { LOG_ER( - "avnd_evt_avnd_avnd_cbk_msg_hdl():Failure:Type:%u Hdl:%llu and Inv:%llu", - cbk_info->type, cbk_info->hdl, cbk_info->inv); + "avnd_evt_avnd_avnd_cbk_msg_hdl():Failure:Type:%u Hdl:%llu and Inv:%llu", + cbk_info->type, cbk_info->hdl, cbk_info->inv); } TRACE_LEAVE2("%u", rc); diff --git a/src/amf/amfnd/avnd_cb.h b/src/amf/amfnd/avnd_cb.h index 8b0cc23..a2e5213 100644 --- a/src/amf/amfnd/avnd_cb.h +++ b/src/amf/amfnd/avnd_cb.h @@ -125,6 +125,8 @@ typedef struct avnd_cb_tag { SaTimeT scs_absence_max_duration; /* the timer for supervision of the absence of SC */ AVND_TMR sc_absence_tmr; + // Used for storing comp, residing on other node. + AmfDb<std::string, AVND_COMP> compdb_internode; } AVND_CB; #define AVND_CB_NULL ((AVND_CB *)0) diff --git a/src/amf/amfnd/avnd_comp.h b/src/amf/amfnd/avnd_comp.h index 49c610e..bbc2aa0 100644 --- a/src/amf/amfnd/avnd_comp.h +++ b/src/amf/amfnd/avnd_comp.h @@ -296,6 +296,8 @@ typedef struct avnd_pxied_rec { #define AVND_COMP_TYPE_LOCAL_NODE 0x00000001 #define AVND_COMP_TYPE_INTER_NODE 0x00000002 #define AVND_COMP_TYPE_EXT_CLUSTER 0x00000004 +// Not for proxy or proxied, it is used for error report, etc. +#define AVND_COMP_TYPE_INTER_NODE_NP 0x00000008 /*########################################################################## COMPONENT DEFINITION (TOP LEVEL) diff --git a/src/amf/amfnd/clm.cc b/src/amf/amfnd/clm.cc index 73c8ff8..317674f 100644 --- a/src/amf/amfnd/clm.cc +++ b/src/amf/amfnd/clm.cc @@ -50,7 +50,8 @@ static void clm_node_left(SaClmNodeIdT node_id) { TRACE_ENTER2("%u", node_id); - if (node_id == avnd_cb->node_info.nodeId) { + if ((node_id == avnd_cb->node_info.nodeId) && + (avnd_cb->node_info.member == SA_TRUE)) { /* if you received a node left indication from clm for self node terminate all the non_ncs components; ncs components :-TBD */ @@ -63,7 +64,39 @@ static void clm_node_left(SaClmNodeIdT node_id) { } } goto done; - } + } else { + AVND_COMP *comp = nullptr; + uint32_t rc; + std::string name = ""; + LOG_NO("Node Id:'%d'", node_id); + // Delete the responses, which was expected to come from this node. + while (nullptr != (comp = + avnd_compdb_rec_get_next(avnd_cb->compdb_internode, name))) { + name = comp->name; + // Check the node id + TRACE("Comp '%s'", comp->name.c_str()); + if (comp->node_id == node_id) { + TRACE("Comp '%s' matched", comp->name.c_str()); + if (comp->comp_type == AVND_COMP_TYPE_INTER_NODE_NP) { + // We have to forward this message to AvA. As of now + // hardcode the value of ERROR_REPORT. + rc = avnd_amf_resp_send(avnd_cb, AVSV_AMF_ERR_REP, + SA_AIS_ERR_TIMEOUT, nullptr, + &comp->reg_dest, &comp->mds_ctxt, + nullptr, false); + if (NCSCC_RC_SUCCESS != rc) { + LOG_ER("Sending error response failed for %s", + comp->name.c_str()); + } + TRACE("Comp '%s' deleted from internode comp DB", + comp->name.c_str()); + avnd_cb->compdb_internode.erase(comp->name); + delete comp; + name = ""; + } // comp type + } // Node id match + } // while loop + } // Different node id. /* We received a node left indication for external node, check if any internode component related to this Node exists */ @@ -222,13 +255,9 @@ static void clm_track_cb( if (false == avnd_cb->first_time_up) { /* When node reboots, we will get an exit cbk, so ignore if avnd_cb->first_time_up is false. */ - if ((notifItem->clusterNode.nodeId == avnd_cb->node_info.nodeId) && - (avnd_cb->node_info.member == SA_TRUE)) { - // Act only once on CLM callback. - clm_node_left(notifItem->clusterNode.nodeId); - } + // Act only once on CLM callback. + clm_node_left(notifItem->clusterNode.nodeId); } - } else if (notifItem->clusterChange == SA_CLM_NODE_RECONFIGURED) { if (avnd_cb->node_info.nodeId == notifItem->clusterNode.nodeId) { TRACE("local CLM node reconfigured"); @@ -253,6 +282,8 @@ static void clm_track_cb( if (avnd_cb->amf_nodeName.empty()) clm_to_amf_node(); avnd_send_node_up_msg(); avnd_cb->first_time_up = false; + } else { + avnd_cb->node_info.member = SA_TRUE; } } } else diff --git a/src/amf/amfnd/err.cc b/src/amf/amfnd/err.cc index aeec373..195c8a3 100644 --- a/src/amf/amfnd/err.cc +++ b/src/amf/amfnd/err.cc @@ -59,9 +59,10 @@ */ #include "amf/amfnd/avnd.h" +#include "osaf/immutil/immutil.h" +#include "amf/amfnd/imm.h" /* static function declarations */ - static uint32_t avnd_err_escalate(AVND_CB *, AVND_SU *, AVND_COMP *, uint32_t *); @@ -173,9 +174,32 @@ uint32_t avnd_evt_ava_err_rep_evh(AVND_CB *cb, AVND_EVT *evt) { /* check if component exists on local AvND node */ comp = avnd_compdb_rec_get(cb->compdb, Amf::to_string(&err_rep->err_comp)); - if (!comp) amf_rc = SA_AIS_ERR_NOT_EXIST; - /* determine other error codes, if any */ + if (!comp) { + // Send the message to imm reader thread for further processing + TRACE("Err_Rep: Sending to Imm thread."); + AVSV_NDA_AVA_MSG *ava_msg = + static_cast<AVSV_NDA_AVA_MSG *>(calloc(1, sizeof(AVSV_NDA_AVA_MSG))); + memcpy(ava_msg, evt->info.ava.msg, sizeof(AVSV_NDA_AVA_MSG)); + AVND_EVT *evt_er = avnd_evt_create(cb, AVND_EVT_AVA_ERR_REP, + &evt->mds_ctxt, &api_info->dest, reinterpret_cast<void *>(ava_msg), 0, 0); + rc = m_NCS_IPC_SEND(&ir_cb.mbx, evt_er, evt_er->priority); + if (NCSCC_RC_SUCCESS != rc) { + LOG_CR("AvND send event to IR mailbox failed, type = %u", evt_er->type); + /* if failure, free the event */ + avnd_evt_destroy(evt_er); + amf_rc = SA_AIS_ERR_TRY_AGAIN; + } else { + goto done; + } + } + + // If this node is disabled or is not a member of Clm cluster, then + // return Unavailable for any operation like this. + if (comp && (cb->node_info.member == false)) { + amf_rc = SA_AIS_ERR_UNAVAILABLE; + goto send_resp; + } /* We need not entertain errors when comp is not in shape */ if (comp && (m_AVND_COMP_PRES_STATE_IS_UNINSTANTIATED(comp) || @@ -209,6 +233,7 @@ uint32_t avnd_evt_ava_err_rep_evh(AVND_CB *cb, AVND_EVT *evt) { comp->name.c_str()); amf_rc = SA_AIS_ERR_NOT_SUPPORTED; } +send_resp: /* send the response back to AvA */ rc = avnd_amf_resp_send(cb, AVSV_AMF_ERR_REP, amf_rc, 0, &api_info->dest, &evt->mds_ctxt, comp, msg_from_avnd); diff --git a/src/amf/amfnd/imm.cc b/src/amf/amfnd/imm.cc index f6b175a..24db31a 100644 --- a/src/amf/amfnd/imm.cc +++ b/src/amf/amfnd/imm.cc @@ -18,8 +18,10 @@ #include <thread> #include <atomic> +#include <string> #include "amf/amfnd/avnd.h" #include <poll.h> +#include "osaf/immutil/immutil.h" #include "amf/amfnd/imm.h" ir_cb_t ir_cb; @@ -106,45 +108,217 @@ void ImmReader::ir_process_event(AVND_EVT *evt) { uint32_t res = NCSCC_RC_SUCCESS; AVND_SU *su = 0; TRACE_ENTER2("Evt type:%u", evt->type); + if (AVND_EVT_IR == evt->type) { + /* get the su */ + su = avnd_sudb_rec_get(avnd_cb->sudb, + Amf::to_string(&evt->info.ir_evt.su_name)); + if (!su) { + TRACE("SU'%s', not found in DB", + osaf_extended_name_borrow(&evt->info.ir_evt.su_name)); + goto done; + } - /* get the su */ - su = avnd_sudb_rec_get(avnd_cb->sudb, - Amf::to_string(&evt->info.ir_evt.su_name)); - if (!su) { - TRACE("SU'%s', not found in DB", - osaf_extended_name_borrow(&evt->info.ir_evt.su_name)); - goto done; - } - - if (false == su->is_ncs) { - res = avnd_comp_config_get_su(su); - } else { - res = NCSCC_RC_FAILURE; - } + if (false == su->is_ncs) { + res = avnd_comp_config_get_su(su); + } else { + res = NCSCC_RC_FAILURE; + } - { - AVND_EVT *evt_ir = 0; - SaNameT copy_name; - TRACE("Sending to main thread."); - osaf_extended_name_alloc(su->name.c_str(), ©_name); - evt_ir = + { + AVND_EVT *evt_ir = 0; + SaNameT copy_name; + TRACE("Sending to main thread."); + osaf_extended_name_alloc(su->name.c_str(), ©_name); + evt_ir = avnd_evt_create(avnd_cb, AVND_EVT_IR, 0, nullptr, ©_name, 0, 0); - osaf_extended_name_free(©_name); - if (res == NCSCC_RC_SUCCESS) - evt_ir->info.ir_evt.status = true; - else - evt_ir->info.ir_evt.status = false; + osaf_extended_name_free(©_name); + if (res == NCSCC_RC_SUCCESS) + evt_ir->info.ir_evt.status = true; + else + evt_ir->info.ir_evt.status = false; + + res = m_NCS_IPC_SEND(&avnd_cb->mbx, evt_ir, evt_ir->priority); + + if (NCSCC_RC_SUCCESS != res) + LOG_CR("AvND send event to main thread mailbox failed, type = %u", + evt_ir->type); + + TRACE("Imm Read:'%d'", evt_ir->info.ir_evt.status); + + /* if failure, free the event */ + if (NCSCC_RC_SUCCESS != res) avnd_evt_destroy(evt_ir); + } + } else if (AVND_EVT_AVA_ERR_REP == evt->type) { + AVSV_AMF_API_INFO *api_info = &evt->info.ava.msg->info.api_info; + AVSV_AMF_ERR_REP_PARAM *err_rep = &api_info->param.err_rep; + SaAisErrorT amf_rc = SA_AIS_OK; + AVND_COMP *comp = 0; + SaImmHandleT immOmHandle = 0; + SaVersionT immVersion = {'A', 2, 15}; + SaImmAccessorHandleT accessorHandle = 0; + const SaImmAttrValuesT_2 **attributes; + std::string su_name; + SaNameT node_name, clm_node_name; + SaClmNodeIdT node_id; + SaAisErrorT error; + // Check if this component is already in the internode db. + // If it is, then it means that Error Report operation + // is already undergoing on this comp, so return TRY_AGAIN. + if (nullptr != + avnd_cb->compdb_internode.find(Amf::to_string(&err_rep->err_comp))) { + LOG_NO("Already Error Report Operation undergoing on '%s'", + Amf::to_string(&err_rep->err_comp).c_str()); + amf_rc = SA_AIS_ERR_TRY_AGAIN; + goto imm_not_initialized; + } + // Check if component is configured in the Cluster. + error = saImmOmInitialize_cond(&immOmHandle, nullptr, &immVersion); + if (error != SA_AIS_OK) { + LOG_ER("saImmOmInitialize failed: %u", error); + amf_rc = SA_AIS_ERR_TRY_AGAIN; + goto imm_not_initialized; + } + + error = amf_saImmOmAccessorInitialize(immOmHandle, accessorHandle); + if (error != SA_AIS_OK) { + LOG_ER("amf_saImmOmAccessorInitialize failed: %u", error); + amf_rc = SA_AIS_ERR_TRY_AGAIN; + goto immOmHandle_finalize; + } + + // Find the component in the Imm DB. + if ((error = amf_saImmOmAccessorGet_o2( + immOmHandle, accessorHandle, Amf::to_string(&err_rep->err_comp), nullptr, + reinterpret_cast<SaImmAttrValuesT_2 ***> + (const_cast<SaImmAttrValuesT_2 ***>(&attributes)))) != SA_AIS_OK) { + if (error == SA_AIS_ERR_NOT_EXIST) { + LOG_NO("Component '%s' is not configured", + Amf::to_string(&err_rep->err_comp).c_str()); + amf_rc = SA_AIS_ERR_NOT_EXIST; + } else { + LOG_ER("amf_saImmOmAccessorGet_o2(for Comp '%s') failed: %u", + Amf::to_string(&err_rep->err_comp).c_str(), error); + amf_rc = SA_AIS_ERR_TRY_AGAIN; + } + + goto immOmAccessor_finalize; + } + + // Component is configured. Now, extract SU name from comp name. + avnd_cpy_SU_DN_from_DN(su_name, Amf::to_string(&err_rep->err_comp)); + TRACE("SU name '%s'", su_name.c_str()); - res = m_NCS_IPC_SEND(&avnd_cb->mbx, evt_ir, evt_ir->priority); + // Get the SU attributes from Imm DB. + if ((error = amf_saImmOmAccessorGet_o2( + immOmHandle, accessorHandle, su_name, nullptr, + reinterpret_cast<SaImmAttrValuesT_2 ***> + (const_cast<SaImmAttrValuesT_2 ***>(&attributes)))) != SA_AIS_OK) { + if (error == SA_AIS_ERR_NOT_EXIST) { + LOG_NO("SU '%s' is not configured", su_name.c_str()); + amf_rc = SA_AIS_ERR_NOT_EXIST; + } else { + LOG_ER("amf_saImmOmAccessorGet_o2(for SU '%s') failed: %u", + su_name.c_str(), error); + amf_rc = SA_AIS_ERR_TRY_AGAIN; + } + + goto immOmAccessor_finalize; + } - if (NCSCC_RC_SUCCESS != res) - LOG_CR("AvND send event to main thread mailbox failed, type = %u", - evt_ir->type); + // Get Amf node name, where this SU is hosted. + (void)immutil_getAttr(const_cast<SaImmAttrNameT>("saAmfSUHostedByNode"), + attributes, 0, &node_name); + TRACE("Hosting Amf node '%s'", Amf::to_string(&node_name).c_str()); + + // Get Amf node attributes from Imm DB. + if ((error = amf_saImmOmAccessorGet_o2( + immOmHandle, accessorHandle, Amf::to_string(&node_name), nullptr, + reinterpret_cast<SaImmAttrValuesT_2 ***> + (const_cast<SaImmAttrValuesT_2 ***>(&attributes)))) != SA_AIS_OK) { + if (error == SA_AIS_ERR_NOT_EXIST) { + LOG_NO("Amf Node '%s' is not configured", + Amf::to_string(&node_name).c_str()); + amf_rc = SA_AIS_ERR_NOT_EXIST; + } else { + LOG_ER("amf_saImmOmAccessorGet_o2(for node '%s') failed: %u", + Amf::to_string(&node_name).c_str(), error); + amf_rc = SA_AIS_ERR_TRY_AGAIN; + } + + goto immOmAccessor_finalize; + } + TRACE("Hosting Amf node '%s' found.", Amf::to_string(&node_name).c_str()); - TRACE("Imm Read:'%d'", evt_ir->info.ir_evt.status); + // Find the Clm Node name from Amf node attributes. + (void)immutil_getAttr(const_cast<SaImmAttrNameT>("saAmfNodeClmNode"), + attributes, 0, &clm_node_name); + TRACE("Clm node name '%s'", Amf::to_string(&clm_node_name).c_str()); - /* if failure, free the event */ - if (NCSCC_RC_SUCCESS != res) avnd_evt_destroy(evt_ir); + // Get Clm node attributes from Imm DB. + if ((error = amf_saImmOmAccessorGet_o2( + immOmHandle, accessorHandle, Amf::to_string(&clm_node_name), + nullptr, reinterpret_cast<SaImmAttrValuesT_2 ***> + (const_cast<SaImmAttrValuesT_2 ***>(&attributes)))) != SA_AIS_OK) { + if (error == SA_AIS_ERR_NOT_EXIST) { + LOG_NO("Clm Node '%s' is not configured", + Amf::to_string(&clm_node_name).c_str()); + amf_rc = SA_AIS_ERR_NOT_EXIST; + } else { + LOG_ER("amf_saImmOmAccessorGet_o2(for clm node '%s') failed: %u", + Amf::to_string(&clm_node_name).c_str(), error); + amf_rc = SA_AIS_ERR_TRY_AGAIN; + } + + goto immOmAccessor_finalize; + } + TRACE("Clm node '%s' found.", Amf::to_string(&clm_node_name).c_str()); + + // Find the configured value of saClmNodeID from Clm node attributes. + (void)immutil_getAttr(const_cast<SaImmAttrNameT>("saClmNodeID"), + attributes, 0, &node_id); + TRACE("Node id '%u'", node_id); + + // We have all the information, send the event to the destined node. + res = avnd_avnd_msg_send(avnd_cb, reinterpret_cast<uint8_t *>(api_info), + api_info->type, &evt->mds_ctxt, node_id); + if (NCSCC_RC_SUCCESS != res) { + // We couldn't send this to the destined AvND, tell user to try again. + amf_rc = SA_AIS_ERR_UNAVAILABLE; + LOG_ER("avnd_int_ext_comp_hdlr:Msg Send Failed: '%u'", res); + goto immOmAccessor_finalize; + } else { + TRACE("avnd_avnd_msg_send:Msg Send Success"); + // Add the internode component in the DB + comp = new AVND_COMP(); + comp->name = Amf::to_string(&err_rep->err_comp); + comp->node_id = node_id; + comp->reg_dest = api_info->dest; + comp->mds_ctxt = evt->mds_ctxt; + comp->comp_type = AVND_COMP_TYPE_INTER_NODE_NP; + // Add to the internode available compdb. + res = avnd_cb->compdb_internode.insert(comp->name, comp); + if (NCSCC_RC_SUCCESS != res) { + delete comp; + comp = nullptr; + amf_rc = SA_AIS_ERR_TRY_AGAIN; + LOG_ER("compdb_internode.insert failed: '%u'", res); + goto immOmAccessor_finalize; + } + immutil_saImmOmAccessorFinalize(accessorHandle); + immutil_saImmOmFinalize(immOmHandle); + goto done; + } +immOmAccessor_finalize: + immutil_saImmOmAccessorFinalize(accessorHandle); +immOmHandle_finalize: + immutil_saImmOmFinalize(immOmHandle); +imm_not_initialized: + /* send the response back to AvA */ + res = avnd_amf_resp_send(avnd_cb, AVSV_AMF_ERR_REP, amf_rc, 0, + &api_info->dest, &evt->mds_ctxt, comp, 0); + if (NCSCC_RC_SUCCESS != res) { + LOG_ER("avnd_amf_resp_send() failed: %u", res); + } } done: if (evt) avnd_evt_destroy(evt); -- 2.7.4 _______________________________________________ Opensaf-devel mailing list Opensaf-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/opensaf-devel