This ticket adds support for container/contained in amfd. --- src/amf/amfd/comp.cc | 65 ++++++++++++++++++-- src/amf/amfd/comp.h | 4 +- src/amf/amfd/comptype.cc | 6 +- src/amf/amfd/csi.cc | 6 ++ src/amf/amfd/csi.h | 3 + src/amf/amfd/ndproc.cc | 14 +++++ src/amf/amfd/node.cc | 29 +++++++++ src/amf/amfd/node.h | 1 + src/amf/amfd/sg.cc | 29 +++++++++ src/amf/amfd/sg.h | 4 ++ src/amf/amfd/sgproc.cc | 142 ++++++++++++++++++++++++++++++++++++++++++- src/amf/amfd/si.cc | 17 ++++++ src/amf/amfd/si.h | 1 + src/amf/amfd/su.cc | 155 ++++++++++++++++++++++++++++++++++++++++++++++- src/amf/amfd/su.h | 15 ++++- src/amf/amfd/util.cc | 39 ++++++++++++ src/amf/amfd/util.h | 2 + 17 files changed, 517 insertions(+), 15 deletions(-)
diff --git a/src/amf/amfd/comp.cc b/src/amf/amfd/comp.cc index 482322d2e..571ac34fb 100644 --- a/src/amf/amfd/comp.cc +++ b/src/amf/amfd/comp.cc @@ -73,7 +73,7 @@ void AVD_COMP::initialize() { curr_num_csi_actv = {}; curr_num_csi_stdby = {}; comp_proxy_csi = {}; - comp_container_csi = {}; + saAmfCompContainerCsi = {}; saAmfCompRestartCount = {}; saAmfCompCurrProxyName = {}; saAmfCompCurrProxiedNames = {}; @@ -357,7 +357,10 @@ static int is_config_valid(const std::string &dn, 0, &aname); osafassert(rc == SA_AIS_OK); - if (comptype_db->find(Amf::to_string(&aname)) == nullptr) { + AVD_COMP_TYPE *comptype(comptype_db->find(Amf::to_string(&aname))); + CcbUtilOperationData_t *ccbCompTypeOpData(nullptr); + + if (comptype == nullptr) { /* Comp type does not exist in current model, check CCB */ if (opdata == nullptr) { report_ccb_validation_error(opdata, "'%s' does not exist in model", @@ -365,7 +368,8 @@ static int is_config_valid(const std::string &dn, return 0; } - if (ccbutil_getCcbOpDataByDN(opdata->ccbId, &aname) == nullptr) { + ccbCompTypeOpData = ccbutil_getCcbOpDataByDN(opdata->ccbId, &aname); + if (ccbCompTypeOpData == nullptr) { report_ccb_validation_error( opdata, "'%s' does not exist in existing model or in CCB", osaf_extended_name_borrow(&aname)); @@ -399,6 +403,24 @@ static int is_config_valid(const std::string &dn, return 0; } + if ((comptype && IS_COMP_CONTAINED(comptype->saAmfCtCompCategory)) || + (ccbCompTypeOpData && + ccbCompTypeOpData->operationType == CCBUTIL_CREATE && + immutil_getAttr(const_cast<SaImmAttrNameT>("saAmfCtCompCategory"), + ccbCompTypeOpData->param.create.attrValues, + 0, &value) == SA_AIS_OK && + value & SA_AMF_COMP_CONTAINED)) { + rc = immutil_getAttr(const_cast<SaImmAttrNameT>("saAmfCompContainerCsi"), + attributes, 0, &value); + if (rc != SA_AIS_OK) { + report_ccb_validation_error( + opdata, "Contained component '%s' must have saAmfCompContainerCsi " + "attribute set", dn.c_str()); + return 0; + } + } + + #if 0 if ((comp->comp_info.category == AVSV_COMP_TYPE_SA_AWARE) && (comp->comp_info.init_len == 0)) { LOG_ER("Sa Aware Component: instantiation command not configured"); @@ -716,6 +738,20 @@ static AVD_COMP *comp_create(const std::string &dn, &comp->comp_info.comp_restart) != SA_AIS_OK) comp->comp_info.comp_restart = comptype->saAmfCtDefDisableRestart; + if (comp->contained()) { + SaNameT container_csi; + + if (immutil_getAttr(const_cast<SaImmAttrNameT>("saAmfCompContainerCsi"), + attributes, 0, &container_csi) != SA_AIS_OK) { + LOG_ER("unable to get container csi for %s", dn.c_str()); + goto done; + } + + comp->saAmfCompContainerCsi = Amf::to_string(&container_csi); + //XXX TODO_70: verify db if container csi. DO we requre this. + container_csis.insert(comp->saAmfCompContainerCsi); + } + comp->max_num_csi_actv = -1; // TODO comp->max_num_csi_stdby = -1; // TODO @@ -770,6 +806,7 @@ SaAisErrorT avd_comp_config_get(const std::string &su_name, AVD_SU *su) { const_cast<SaImmAttrNameT>("saAmfCompQuiescingCompleteTimeout"), const_cast<SaImmAttrNameT>("saAmfCompRecoveryOnError"), const_cast<SaImmAttrNameT>("saAmfCompDisableRestart"), + const_cast<SaImmAttrNameT>("saAmfCompContainerCsi"), nullptr}; TRACE_ENTER(); @@ -1735,9 +1772,9 @@ static void comp_ccb_apply_modify_hdlr(struct CcbUtilOperationData *opdata) { comp->comp_proxy_csi = Amf::to_string((SaNameT *)value); } else if (!strcmp(attribute->attrName, "saAmfCompContainerCsi")) { if (value_is_deleted) - comp->comp_proxy_csi = ""; + comp->saAmfCompContainerCsi = ""; else - comp->comp_container_csi = Amf::to_string((SaNameT *)value); + comp->saAmfCompContainerCsi = Amf::to_string((SaNameT *)value); } else { osafassert(0); } @@ -1842,6 +1879,8 @@ void avd_comp_constructor(void) { bool AVD_COMP::is_preinstantiable() const { AVSV_COMP_TYPE_VAL category = comp_info.category; return ((category == AVSV_COMP_TYPE_SA_AWARE) || + (category == AVSV_COMP_TYPE_CONTAINER) || + (category == AVSV_COMP_TYPE_CONTAINED) || (category == AVSV_COMP_TYPE_PROXIED_LOCAL_PRE_INSTANTIABLE) || (category == AVSV_COMP_TYPE_EXTERNAL_PRE_INSTANTIABLE)); } @@ -1904,3 +1943,19 @@ bool AVD_COMP::proxied_npi() const { AVD_COMP_TYPE *comptype = comptype_db->find(saAmfCompType); return (IS_COMP_PROXIED_NPI(comptype->saAmfCtCompCategory)); } +/** + * @brief Checks if component is a container comp. + * @Return true/false. + */ +bool AVD_COMP::container(void) const { + AVD_COMP_TYPE *comptype(comptype_db->find(saAmfCompType)); + return (IS_COMP_CONTAINER(comptype->saAmfCtCompCategory)); +} +/** + * @brief Checks if component is contained comp. + * @Return true/false. + */ +bool AVD_COMP::contained(void) const { + AVD_COMP_TYPE *comptype(comptype_db->find(saAmfCompType)); + return (IS_COMP_CONTAINED(comptype->saAmfCtCompCategory)); +} diff --git a/src/amf/amfd/comp.h b/src/amf/amfd/comp.h index 1493d717c..4265f16d6 100644 --- a/src/amf/amfd/comp.h +++ b/src/amf/amfd/comp.h @@ -141,7 +141,7 @@ class AVD_COMP { * Checkpointing - Sent update independently. */ std::string comp_proxy_csi; - std::string comp_container_csi; + std::string saAmfCompContainerCsi; /* runtime attributes */ SaAmfOperationalStateT saAmfCompOperState; @@ -166,6 +166,8 @@ class AVD_COMP { bool saaware() const; bool proxied_pi() const; bool proxied_npi() const; + bool container(void) const; + bool contained(void) const; private: void initialize(); diff --git a/src/amf/amfd/comptype.cc b/src/amf/amfd/comptype.cc index 787c0bcb6..843a406aa 100644 --- a/src/amf/amfd/comptype.cc +++ b/src/amf/amfd/comptype.cc @@ -223,9 +223,8 @@ static bool config_is_valid(const std::string &dn, attributes, 0, &category); osafassert(rc == SA_AIS_OK); - /* We do not support Proxy, Container and Contained as of now. */ - if (IS_COMP_PROXY(category) || IS_COMP_CONTAINER(category) || - IS_COMP_CONTAINED(category)) { + /* We do not support Proxy as of now. */ + if (IS_COMP_PROXY(category)) { report_ccb_validation_error( opdata, "Unsupported saAmfCtCompCategory value '%u' for '%s'", category, dn.c_str()); @@ -312,6 +311,7 @@ static bool config_is_valid(const std::string &dn, */ if (IS_COMP_LOCAL(category) && !(IS_COMP_PROXIED(category) || IS_COMP_PROXIED_NPI(category)) && + !IS_COMP_CONTAINER(category) && !IS_COMP_CONTAINED(category) && !IS_COMP_SAAWARE(category)) { attr_name = "saAmfCtRelPathTerminateCmd"; diff --git a/src/amf/amfd/csi.cc b/src/amf/amfd/csi.cc index 82829566c..f7e3730dd 100644 --- a/src/amf/amfd/csi.cc +++ b/src/amf/amfd/csi.cc @@ -26,6 +26,7 @@ #include "amf/amfd/proc.h" AmfDb<std::string, AVD_CSI> *csi_db = nullptr; +std::set<std::string> container_csis; // AVD_COMP *AVD_CSI::find_assigned_comp( @@ -1670,3 +1671,8 @@ void avd_compcsi_cleanup_imm_object(AVD_CL_CB *cb) { done: TRACE_LEAVE(); } + +bool AVD_CSI::is_container_csi(void) const { + auto iter(container_csis.find(name)); + return (iter != container_csis.end()) ? true : false; +} diff --git a/src/amf/amfd/csi.h b/src/amf/amfd/csi.h index 837fbc67d..166d9dec4 100644 --- a/src/amf/amfd/csi.h +++ b/src/amf/amfd/csi.h @@ -98,6 +98,8 @@ class AVD_CSI { const std::string &cstype, const AVD_SU_SI_REL *sisu, const std::vector<AVD_COMP *> &list_of_comp); + bool is_container_csi(void) const; + private: AVD_CSI(); // disallow copy and assign @@ -106,6 +108,7 @@ class AVD_CSI { }; extern AmfDb<std::string, AVD_CSI> *csi_db; +extern std::set<std::string> container_csis; class AVD_CS_TYPE { public: diff --git a/src/amf/amfd/ndproc.cc b/src/amf/amfd/ndproc.cc index 31d2263d2..eb5d2b3d8 100644 --- a/src/amf/amfd/ndproc.cc +++ b/src/amf/amfd/ndproc.cc @@ -1113,6 +1113,20 @@ void avd_data_update_req_evh(AVD_CL_CB *cb, AVD_EVT *evt) { /* send response to pending clm callback */ if (su->su_on_node->clm_pend_inv != 0) clm_pend_response(su, static_cast<SaAmfPresenceStateT>(l_val)); + + /* + * If the contained su has finished terminating we can now finish + * with the container su. + */ + if (su->contained() && l_val == SA_AMF_PRESENCE_UNINSTANTIATED) { + AVD_SU *container_su(su->get_container_su_on_same_node()); + + if (container_su->wait_for_contained_to_quiesce) { + // XXX fix me, could be quiescing + avd_sg_su_si_mod_snd(cb, container_su, SA_AMF_HA_QUIESCED); + container_su->wait_for_contained_to_quiesce = false; + } + } } else { /* log error that a the value len is invalid */ LOG_ER("%s:%u: %u", __FILE__, __LINE__, diff --git a/src/amf/amfd/node.cc b/src/amf/amfd/node.cc index 0ffcfb782..b5ff0eab3 100644 --- a/src/amf/amfd/node.cc +++ b/src/amf/amfd/node.cc @@ -1676,3 +1676,32 @@ bool AVD_AVND::is_campaign_set_for_all_sus() const { return false; } } + +void AVD_AVND::instantiate_contained_sus(AVD_SU *container_su, + const AVD_CSI *container_csi) { + TRACE_ENTER(); + for (auto &su : list_of_su) { + if (su == container_su) + continue; + if ((su->contained() == false) || + (su->list_of_comp.empty() == true) || + (su->saAmfSUPresenceState == SA_AMF_PRESENCE_INSTANTIATED)) + continue; + if (su->list_of_comp.front()->saAmfCompContainerCsi == container_csi->name) { + if (((su->su_on_node->node_state == AVD_AVND_STATE_PRESENT) || + (su->su_on_node->node_state == AVD_AVND_STATE_NO_CONFIG) || + (su->su_on_node->node_state == AVD_AVND_STATE_NCS_INIT)) && + ((su->su_on_node->saAmfNodeAdminState != SA_AMF_ADMIN_LOCKED_INSTANTIATION) && + (su->sg_of_su->saAmfSGAdminState != SA_AMF_ADMIN_LOCKED_INSTANTIATION)) && + ((su->saAmfSUOperState == SA_AMF_OPERATIONAL_ENABLED) || + (su->sg_of_su->sg_ncs_spec == true)) && + (su->sg_of_su->saAmfSGNumPrefInserviceSUs > + sg_instantiated_su_count(su->sg_of_su))) { + if (avd_instantiate_contained_su(avd_cb, container_su, su, false) == NCSCC_RC_SUCCESS) { + su->set_term_state(false); + } + } + } + } + TRACE_LEAVE(); +} diff --git a/src/amf/amfd/node.h b/src/amf/amfd/node.h index e64bf8c93..55e50504a 100644 --- a/src/amf/amfd/node.h +++ b/src/amf/amfd/node.h @@ -148,6 +148,7 @@ class AVD_AVND { bool is_campaign_set_for_all_sus() const; // Member functions. void node_sus_termstate_set(bool term_state) const; + void instantiate_contained_sus(AVD_SU* su, const AVD_CSI *container_csi); private: void initialize(); diff --git a/src/amf/amfd/sg.cc b/src/amf/amfd/sg.cc index f973e3a97..83af5292b 100644 --- a/src/amf/amfd/sg.cc +++ b/src/amf/amfd/sg.cc @@ -497,6 +497,14 @@ SaAisErrorT avd_sg_config_get(const std::string &app_dn, AVD_APP *app) { error = SA_AIS_ERR_FAILED_OPERATION; goto done2; } + + if ((sg->any_container_su() == true) && + (sg->sg_redundancy_model != SA_AMF_N_WAY_ACTIVE_REDUNDANCY_MODEL)) { + LOG_ER("%s: red model for container sg must be N-Way Active: %u", + sg->name.c_str(),sg->sg_redundancy_model); + error = SA_AIS_ERR_FAILED_OPERATION; + goto done2; + } } if (rc == SA_AIS_ERR_NOT_EXIST) { @@ -2400,3 +2408,24 @@ bool AVD_SG::find_instantiable_same_rank_su(AVD_SU *su) { } return false; } + +/** + * @brief Checks if any su of Sg is a container su. + * @return true/false + */ +bool AVD_SG::any_container_su(void) const { + return (std::any_of(list_of_su.begin(), list_of_su.end(), + [&](AVD_SU *su) -> bool { + return su->container(); + })); +} +/** + * @brief Checks if any su of Sg is a contained su. + * @return true/false + */ +bool AVD_SG::any_contained_su(void) const { + return (std::any_of(list_of_su.begin(), list_of_su.end(), + [&](AVD_SU *su) -> bool { + return su->contained(); + })); +} diff --git a/src/amf/amfd/sg.h b/src/amf/amfd/sg.h index 81595a2b1..426f1ba4d 100644 --- a/src/amf/amfd/sg.h +++ b/src/amf/amfd/sg.h @@ -451,6 +451,10 @@ class AVD_SG { // Checks if si_equal_distribution is configured for the SG. bool is_equal() const; bool find_instantiable_same_rank_su(AVD_SU *su); + //Checks if any SU of sg is a container su. + bool any_container_su(void) const; + //Checks if any SU of sg is a contained su. + bool any_contained_su(void) const; private: // disallow copy and assign, TODO(hafe) add common macro for this diff --git a/src/amf/amfd/sgproc.cc b/src/amf/amfd/sgproc.cc index 2bee8754d..7fba62ba7 100644 --- a/src/amf/amfd/sgproc.cc +++ b/src/amf/amfd/sgproc.cc @@ -41,6 +41,8 @@ #include "amf/amfd/si_dep.h" #include "amf/amfd/cluster.h" +extern bool all_assignments_done(const AVD_SU *); + /** * @brief While creating compcsi relationship in SUSI, AMF may assign * a dependent csi to a component in the SU when its one or more @@ -1134,6 +1136,54 @@ void process_su_si_response_for_surestart_admin_op(AVD_SU *su) { } TRACE_LEAVE(); } + +static void process_su_si_response_for_container_contained( + AVD_CL_CB *cb, AVD_SU *su, SaAmfHAStateT state, AVSV_SUSI_ACT msg_act) { + TRACE_ENTER(); + + if (su->container() || su->contained()) { + TRACE("su: %s state: %i msg_act: %i", su->name.c_str(), state, msg_act); + + if (su->contained() && + ((state == SA_AMF_HA_QUIESCED && msg_act == AVSV_SUSI_ACT_DEL) || + (state == SA_AMF_HA_STANDBY && msg_act == AVSV_SUSI_ACT_DEL))) { + // notify container su that contained has quiesced and removed + AVD_SU *container_su(su->get_container_su_on_same_node()); + + TRACE("container: %s wait: %i", + container_su->name.c_str(), + container_su->wait_for_contained_to_quiesce); + + if (container_su->wait_for_contained_to_quiesce) { + // contained SU has been removed, now terminate it + if (avd_snd_presence_msg(avd_cb, su, true) == NCSCC_RC_SUCCESS) + su->set_term_state(true); + + /* + * If all the contained SUs are done change the admin state of the + * contained SG back to unlocked. + */ + bool all_unassigned(true); + for (const auto &iter : su->sg_of_su->list_of_su) { + if (iter->list_of_susi != AVD_SU_SI_REL_NULL) { + all_unassigned = false; + break; + } + } + + if (container_su->sg_of_su->saAmfSGAdminState == SA_AMF_ADMIN_LOCKED && + all_unassigned) { + su->sg_of_su->saAmfSGAdminState = SA_AMF_ADMIN_UNLOCKED; + } + } + } else if (su->container() && state == SA_AMF_HA_ACTIVE) + su->instantiate_associated_contained_sus(); + } + + TRACE_LEAVE(); + return; +} + /***************************************************************************** * Function: avd_su_si_assign_func * @@ -1247,6 +1297,14 @@ void avd_su_si_assign_evh(AVD_CL_CB *cb, AVD_EVT *evt) { TRACE("%u", n2d_msg->msg_info.n2d_su_si_assign.msg_act); switch (n2d_msg->msg_info.n2d_su_si_assign.msg_act) { case AVSV_SUSI_ACT_DEL: + if (su->contained()) { + AVD_SU *container_su(su->get_container_su_on_same_node()); + if (container_su->wait_for_contained_to_quiesce && + container_su->sg_of_su->saAmfSGAdminState == + SA_AMF_ADMIN_LOCKED) { + avd_sg_su_oper_list_del(cb, su, false); + } + } break; case AVSV_SUSI_ACT_MOD: @@ -1724,6 +1782,12 @@ void avd_su_si_assign_evh(AVD_CL_CB *cb, AVD_EVT *evt) { su->su_on_node->clm_pend_inv = 0; } /* else wait for some more time */ } + + process_su_si_response_for_container_contained( + cb, + su, + n2d_msg->msg_info.n2d_su_si_assign.ha_state, + n2d_msg->msg_info.n2d_su_si_assign.msg_act); } /* Check whether the node belonging to this su is disable and susi of all su @@ -1813,7 +1877,8 @@ void avd_sg_app_node_su_inst_func(AVD_CL_CB *cb, AVD_AVND *avnd) { if (cb->init_state == AVD_INIT_DONE) { for (const auto &i_su : avnd->list_of_su) { - if ((i_su->term_state == false) && + if (!i_su->contained() && // contained sus are instantiated by container + (i_su->term_state == false) && (i_su->saAmfSUPresenceState == SA_AMF_PRESENCE_UNINSTANTIATED) && (i_su->saAmfSUAdminState != SA_AMF_ADMIN_LOCKED_INSTANTIATION) && (i_su->sg_of_su->saAmfSGAdminState != @@ -1994,7 +2059,8 @@ uint32_t avd_sg_app_su_inst_func(AVD_CL_CB *cb, AVD_SG *sg) { num_insvc_su++; } - } else if ((i_su->saAmfSUPreInstantiable == true) && + } else if (!i_su->contained() && // contained su instantiated by container + (i_su->saAmfSUPreInstantiable == true) && (i_su->saAmfSUPresenceState == SA_AMF_PRESENCE_UNINSTANTIATED) && ((i_su->saAmfSUAdminState == SA_AMF_ADMIN_UNLOCKED) || @@ -2423,6 +2489,71 @@ done: return rc; } +static uint32_t shutdown_contained_sus(AVD_CL_CB *cb, AVD_SU *container_su, + SaAmfHAStateT state) { + TRACE_ENTER(); + + uint32_t rc(NCSCC_RC_FAILURE); + + // get the container csi + AVD_COMP_CSI_REL *container_csi_rel(nullptr); + + for (const auto &comp : container_su->list_of_comp) { + if (comp->container()) { + for (const auto &si : container_su->sg_of_su->list_of_si) { + for (AVD_CSI *csi = si->list_of_csi; csi; csi = csi->si_list_of_csi_next) { + for (AVD_COMP_CSI_REL *compcsi = csi->list_compcsi; compcsi; + compcsi = compcsi->csi_csicomp_next) { + if (compcsi->comp == comp) { + TRACE("found container csi: %s", compcsi->csi->name.c_str()); + container_csi_rel = compcsi; + break; + } + } + } + } + } + } + + const std::string& container_csi(container_csi_rel->csi->name); + + for (auto &su : container_su->su_on_node->list_of_su) { + if (su == container_su) + continue; + if ((su->contained() == false) || + (su->list_of_comp.empty() == true)) + continue; + if (su->list_of_comp.front()->saAmfCompContainerCsi == container_csi) { + su->set_readiness_state(SA_AMF_READINESS_OUT_OF_SERVICE); + + if (su->list_of_susi->state == SA_AMF_HA_ACTIVE) + rc = avd_sg_su_si_mod_snd(cb, su, SA_AMF_HA_QUIESCED); + else + rc = avd_sg_su_si_del_snd(cb, su); + + if (rc != NCSCC_RC_SUCCESS) + goto done; + + if (container_su->sg_of_su->saAmfSGAdminState == SA_AMF_ADMIN_LOCKED) { + // this is dangerous... + // XXX use ng_using_saAmfSGAdminState + su->sg_of_su->saAmfSGAdminState = SA_AMF_ADMIN_LOCKED; + + su->sg_of_su->set_fsm_state(AVD_SG_FSM_SG_ADMIN); + } else { + su->sg_of_su->set_fsm_state(AVD_SG_FSM_SU_OPER); + } + + avd_sg_su_oper_list_add(cb, su, false); + } + } + +done: + return rc; + + TRACE_LEAVE(); +} + /***************************************************************************** * Function: avd_sg_su_si_mod_snd * @@ -2456,6 +2587,13 @@ uint32_t avd_sg_su_si_mod_snd(AVD_CL_CB *cb, AVD_SU *su, SaAmfHAStateT state) { goto done; } + if (su->container() && !su->wait_for_contained_to_quiesce) { + TRACE("this is a container su; need to shut down contained sus"); + rc = shutdown_contained_sus(cb, su, state); + su->wait_for_contained_to_quiesce = true; + goto done; + } + /* change the state for all assignments to the specified state. */ i_susi = su->list_of_susi; while (i_susi != AVD_SU_SI_REL_NULL) { diff --git a/src/amf/amfd/si.cc b/src/amf/amfd/si.cc index cf026d7b8..5308a7ac8 100644 --- a/src/amf/amfd/si.cc +++ b/src/amf/amfd/si.cc @@ -703,6 +703,13 @@ SaAisErrorT avd_si_config_get(AVD_APP *app) { if (avd_sirankedsu_config_get(si_str, si) != SA_AIS_OK) goto done2; if (avd_csi_config_get(si_str, si) != SA_AIS_OK) goto done2; + + if ((si->sg_of_si != nullptr) && (si->sg_of_si->any_container_su() == true) + && (si->csi_count() > 1)) { + LOG_ER("More than one CSIs configured in a container si:'%s'", + si->name.c_str()); + goto done2; + } } if (rc == SA_AIS_ERR_NOT_EXIST) { @@ -1917,3 +1924,13 @@ SaAisErrorT AVD_SI::si_swap_validate() { done: return rc; } + +uint32_t AVD_SI::csi_count(void) const { + uint32_t count(0); + for (const AVD_CSI *csi(list_of_csi); + csi; + csi = csi->si_list_of_csi_next) { + count++; + } + return count; +} diff --git a/src/amf/amfd/si.h b/src/amf/amfd/si.h index 45b37cc33..cca42a400 100644 --- a/src/amf/amfd/si.h +++ b/src/amf/amfd/si.h @@ -155,6 +155,7 @@ class AVD_SI { uint32_t count_sisu_with(SaAmfHAStateT ha); bool is_all_sponsor_si_unassigned() const; bool is_all_dependent_si_unassigned() const; + uint32_t csi_count(void) const; private: bool is_assigned() const { return list_of_sisu ? true : false; } diff --git a/src/amf/amfd/su.cc b/src/amf/amfd/su.cc index c3609d8aa..2c8256a37 100644 --- a/src/amf/amfd/su.cc +++ b/src/amf/amfd/su.cc @@ -64,6 +64,7 @@ void AVD_SU::initialize() { pend_cbk.invocation = 0; pend_cbk.admin_oper = (SaAmfAdminOperationIdT)0; surestart = false; + wait_for_contained_to_quiesce = false; } AVD_SU::AVD_SU() { initialize(); } @@ -748,6 +749,23 @@ SaAisErrorT avd_su_config_get(const std::string &sg_name, AVD_SG *sg) { error = SA_AIS_ERR_FAILED_OPERATION; goto done2; } + + if (su->any_container_comp() == true) { + if (su->container() == false) { + LOG_ER("%s: comps of other category mixed with container comp: %u", + su->name.c_str(), error); + error = SA_AIS_ERR_FAILED_OPERATION; + goto done2; + } + } + if (su->any_contained_comp() == true) { + if (su->contained() == false) { + LOG_ER("%s: comps of other category mixed with contained comp: %u", + su->name.c_str(), error); + error = SA_AIS_ERR_FAILED_OPERATION; + goto done2; + } + } } if (rc == SA_AIS_ERR_NOT_EXIST) { @@ -1120,6 +1138,9 @@ done: void AVD_SU::unlock_instantiation(SaImmOiHandleT immoi_handle, SaInvocationT invocation) { AVD_AVND *node = get_node_ptr(); + bool is_container_ready = true; + AVD_SU *container_ptr = nullptr; + uint32_t rc; TRACE_ENTER2("'%s'", name.c_str()); @@ -1149,6 +1170,15 @@ void AVD_SU::unlock_instantiation(SaImmOiHandleT immoi_handle, goto done; } + if (contained() == true) { + container_ptr = get_container_su_on_same_node(); + if ((container_ptr == nullptr) || + (container_ptr->is_ready_for_contained() == false)) { + is_container_ready = false; + TRACE("Container su not available or ready."); + } + } + /* Middleware sus are not enabled until node joins. During starting of opensaf, if mw su is locked-in and unlock-in command is issued, su should get instantiated. */ @@ -1160,10 +1190,16 @@ void AVD_SU::unlock_instantiation(SaImmOiHandleT immoi_handle, ((saAmfSUOperState == SA_AMF_OPERATIONAL_ENABLED) || (sg_of_su->sg_ncs_spec == true)) && (sg_of_su->pref_inservice_sus() > - sg_instantiated_su_count(sg_of_su))) { + sg_instantiated_su_count(sg_of_su)) && + (is_container_ready == true)) { /* When the SU will instantiate then prescence state change message will come and so store the callback parameters to send response later on. */ - if (avd_snd_presence_msg(avd_cb, this, false) == NCSCC_RC_SUCCESS) { + if (contained() == true) + rc = avd_instantiate_contained_su(avd_cb, container_ptr, this, false); + else + rc = avd_snd_presence_msg(avd_cb, this, false); + + if (rc == NCSCC_RC_SUCCESS) { set_term_state(false); set_admin_state(SA_AMF_ADMIN_LOCKED); pend_cbk.admin_oper = SA_AMF_ADMIN_UNLOCK_INSTANTIATION; @@ -2359,7 +2395,7 @@ AVD_AVND *AVD_SU::get_node_ptr(void) const { * @param su * @return true if SU can be made in-service */ -bool AVD_SU::is_in_service(void) { +bool AVD_SU::is_in_service(void) const { AVD_AVND *node = get_node_ptr(); const AVD_SG *sg = sg_of_su; const AVD_APP *app = sg->app; @@ -2803,3 +2839,116 @@ uint32_t AVD_SU::count_susi_without_fsm(uint32_t fsm) { } return count; } + +/** + * @brief Checks if all comps of SU are container comps. + * @return true/false + */ +bool AVD_SU::container(void) const { + if (std::all_of(list_of_comp.begin(), list_of_comp.end(), + [&](AVD_COMP *comp) -> bool { + return comp->container(); + })) { + return true; + } else { + return false; + } +} +/** + * @brief Checks if all comps of SU are contained comps. + * @return true/false + */ +bool AVD_SU::contained(void) const { + if (std::all_of(list_of_comp.begin(), list_of_comp.end(), + [&](AVD_COMP *comp) -> bool { + return comp->contained(); + })) { + return true; + } else { + return false; + } +} +/** + * @brief Checks if any comp of SU is a container comp. + * @return true/false + */ +bool AVD_SU::any_container_comp(void) const { + return (std::any_of(list_of_comp.begin(), list_of_comp.end(), + [&](AVD_COMP *comp) -> bool { + return comp->container(); + })); + +} + +/** + * @brief Checks if any comp of SU is a contained comp. + * @return true/false + */ +bool AVD_SU::any_contained_comp(void) const { + return (std::any_of(list_of_comp.begin(), list_of_comp.end(), + [&](AVD_COMP *comp) -> bool { + return comp->contained(); + })); +} + +bool AVD_SU::is_ready_for_contained(void) const { + if ((container() == true) && (list_of_susi != nullptr) && + (is_in_service() == true) && (any_container_csi_assigned() == true)) + return true; + return false; +} + +void AVD_SU::instantiate_associated_contained_sus(void) { + TRACE_ENTER(); + if (is_ready_for_contained() == false) { + TRACE_LEAVE(); + return; + } + for (AVD_SU_SI_REL *susi = list_of_susi; susi != nullptr; + susi = susi->su_next) { + if (susi->fsm != AVD_SU_SI_STATE_ASGND) + continue; + for (AVD_COMP_CSI_REL *compcsi = susi->list_of_csicomp; compcsi; + compcsi = compcsi->susi_csicomp_next) { + if (compcsi->csi->is_container_csi() == true) { + su_on_node->instantiate_contained_sus(this, compcsi->csi); + } + } + } + TRACE_LEAVE(); +} + +bool AVD_SU::any_container_csi_assigned(void) const { + for (AVD_SU_SI_REL *susi = list_of_susi; susi != nullptr; + susi = susi->su_next) { + if (susi->fsm != AVD_SU_SI_STATE_ASGND) + continue; + for (AVD_COMP_CSI_REL *compcsi = susi->list_of_csicomp; compcsi; + compcsi = compcsi->susi_csicomp_next) { + if (compcsi->csi->is_container_csi() == true) + return true; + } + } + return false; +} + +AVD_CSI *AVD_SU::get_container_csi(void) { + if (list_of_comp.empty()) + return nullptr; + auto comp = list_of_comp.front(); + return csi_db->find(comp->saAmfCompContainerCsi); +} + +AVD_SU *AVD_SU::get_container_su_on_same_node(void) { + AVD_CSI *container_csi = get_container_csi(); + if (container_csi != nullptr) { + for (AVD_COMP_CSI_REL *compcsi = container_csi->list_compcsi; + compcsi; + compcsi = compcsi->csi_csicomp_next) { + if (compcsi->comp->su->su_on_node == su_on_node) + return compcsi->comp->su; + } + } + //TODO:70: return a higher rank su always. It should match other function. + return nullptr; +} diff --git a/src/amf/amfd/su.h b/src/amf/amfd/su.h index cf29f25de..7afc5abee 100644 --- a/src/amf/amfd/su.h +++ b/src/amf/amfd/su.h @@ -37,6 +37,7 @@ #include "amf/common/amf_db_template.h" class AVD_SG; +class AVD_CSI; class AVD_SUTYPE; /** @@ -88,6 +89,8 @@ class AVD_SU { int su_act_state; // not used, kept for EDU, remove later + bool wait_for_contained_to_quiesce; + AVD_SG *sg_of_su; /* the service group of this SU */ AVD_AVND *su_on_node; /* the node on which this SU resides */ struct avd_su_si_rel_tag @@ -122,7 +125,7 @@ class AVD_SU { void remove_from_model(); void set_su_switch(SaToggleState state, bool wrt_to_imm = true); AVD_AVND *get_node_ptr(void) const; - bool is_in_service(void); + bool is_in_service(void) const; bool is_instantiable(void); void reset_all_comps_assign_flag(); AVD_COMP *find_unassigned_comp_that_provides_cstype( @@ -156,6 +159,16 @@ class AVD_SU { void set_surestart(bool state); bool get_surestart() const; void update_susis_in_imm_and_ntf(SaAmfHAStateT ha_state) const; + bool any_container_comp(void) const; + bool any_contained_comp(void) const; + bool container(void) const; + bool contained(void) const; + void instantiate_associated_contained_sus(void); + bool is_ready_for_contained(void) const; + bool any_container_csi_assigned(void) const; + AVD_CSI *get_container_csi(void); + AVD_SU *get_container_su_on_same_node(void); + private: void initialize(); diff --git a/src/amf/amfd/util.cc b/src/amf/amfd/util.cc index 288d77483..14a4e0485 100644 --- a/src/amf/amfd/util.cc +++ b/src/amf/amfd/util.cc @@ -2123,3 +2123,42 @@ done: delete d2n_msg; return rc; } + +uint32_t avd_instantiate_contained_su(AVD_CL_CB *cb, AVD_SU *container_su, + AVD_SU *contained_su, bool term_state) { + uint32_t rc = NCSCC_RC_FAILURE; + AVD_DND_MSG *d2n_msg; + AVD_AVND *node = container_su->get_node_ptr(); + + TRACE_ENTER2("%s '%s'", (term_state == true) ? "Terminate" : "Instantiate", + contained_su->name.c_str()); + + /* prepare the node update message. */ + d2n_msg = new AVSV_DND_MSG(); + SaNameT container_su_name, contained_su_name; + osaf_extended_name_alloc(container_su->name.c_str(), &container_su_name); + osaf_extended_name_alloc(contained_su->name.c_str(), &contained_su_name); + + /* prepare the SU presence state change notification message */ + d2n_msg->msg_type = AVSV_D2N_CONTAINED_SU_MSG; + d2n_msg->msg_info.d2n_contained_su_msg_info.msg_id = ++(node->snd_msg_id); + d2n_msg->msg_info.d2n_contained_su_msg_info.node_id = node->node_info.nodeId; + d2n_msg->msg_info.d2n_contained_su_msg_info.container_su_name = container_su_name; + d2n_msg->msg_info.d2n_contained_su_msg_info.contained_su_name = contained_su_name; + d2n_msg->msg_info.d2n_contained_su_msg_info.term_state = term_state; + + TRACE("Sending %u to %x", AVSV_D2N_CONTAINED_SU_MSG, node->node_info.nodeId); + + if (avd_d2n_msg_snd(cb, node, d2n_msg) != NCSCC_RC_SUCCESS) { + LOG_ER("%s: snd to %x failed", __FUNCTION__, node->node_info.nodeId); + d2n_msg_free(d2n_msg); + --(node->snd_msg_id); + goto done; + } + + m_AVSV_SEND_CKPT_UPDT_ASYNC_UPDT(cb, (node), AVSV_CKPT_AVND_SND_MSG_ID); + rc = NCSCC_RC_SUCCESS; +done: + TRACE_LEAVE2("%u", rc); + return rc; +} diff --git a/src/amf/amfd/util.h b/src/amf/amfd/util.h index 28709493b..39ca5a344 100644 --- a/src/amf/amfd/util.h +++ b/src/amf/amfd/util.h @@ -122,5 +122,7 @@ uint32_t avd_snd_compcsi_msg(AVD_COMP *comp, AVD_CSI *csi, avd_comp_csi_rel_tag *compcsi, AVSV_COMPCSI_ACT act); uint32_t avd_send_reboot_msg_directly(AVD_AVND *node); +uint32_t avd_instantiate_contained_su(AVD_CL_CB *cb, AVD_SU *container_su, + AVD_SU *contained_su, bool term_state); #endif // AMF_AMFD_UTIL_H_ -- 2.14.4 ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot _______________________________________________ Opensaf-devel mailing list Opensaf-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/opensaf-devel