osaf/services/saf/amf/amfd/cluster.cc | 7 +++- osaf/services/saf/amf/amfd/include/sg.h | 2 + osaf/services/saf/amf/amfd/include/susi.h | 1 + osaf/services/saf/amf/amfd/ndfsm.cc | 6 ++- osaf/services/saf/amf/amfd/sg.cc | 42 +++++++++++++++++++++++++ osaf/services/saf/amf/amfd/sg_2n_fsm.cc | 13 +++++-- osaf/services/saf/amf/amfd/sgproc.cc | 28 +++++++++++++--- osaf/services/saf/amf/amfd/siass.cc | 52 ++++++++++++++++++++++++++---- osaf/services/saf/amf/amfd/su.cc | 19 +++++++--- 9 files changed, 144 insertions(+), 26 deletions(-)
When a payload restarts or is powered off during headless, the SUSI assignments in this payload were removed, that shall break down the HA characteristic of SUSI assignments after headless. This patch treats the SUSI assignments removed during headless as ABSENT SUSI, and reuse node_fail() to perform a failover on SU having ABSENT SUSIs, in order that the HA of SUSI assignments shall become STABLE, which means no QUIESCED/QUIESCING SUSI, etc... Inside node_fail(), any su_si assignments event on ABSENT SUSI toward AMFND likes modification, deletion will ignored. diff --git a/osaf/services/saf/amf/amfd/cluster.cc b/osaf/services/saf/amf/amfd/cluster.cc --- a/osaf/services/saf/amf/amfd/cluster.cc +++ b/osaf/services/saf/amf/amfd/cluster.cc @@ -84,7 +84,12 @@ void avd_cluster_tmr_init_evh(AVD_CL_CB } if (i_sg->any_assignment_in_progress() == false) { - i_sg->set_fsm_state(AVD_SG_FSM_STABLE); + if (i_sg->any_assignment_absent() == false) { + i_sg->set_fsm_state(AVD_SG_FSM_STABLE); + } else { + // failover with ABSENT SUSI, which had already been removed during headless + i_sg->failover_absent_assignment(); + } } if (i_sg->sg_fsm_state == AVD_SG_FSM_STABLE) diff --git a/osaf/services/saf/amf/amfd/include/sg.h b/osaf/services/saf/amf/amfd/include/sg.h --- a/osaf/services/saf/amf/amfd/include/sg.h +++ b/osaf/services/saf/amf/amfd/include/sg.h @@ -415,6 +415,8 @@ public: bool is_sg_serviceable_outside_ng(const AVD_AMF_NG *ng); SaAisErrorT check_sg_stability(); bool any_assignment_in_progress(); + bool any_assignment_absent(); + void failover_absent_assignment(); bool ng_using_saAmfSGAdminState; uint32_t term_su_list_in_reverse(); diff --git a/osaf/services/saf/amf/amfd/include/susi.h b/osaf/services/saf/amf/amfd/include/susi.h --- a/osaf/services/saf/amf/amfd/include/susi.h +++ b/osaf/services/saf/amf/amfd/include/susi.h @@ -70,6 +70,7 @@ typedef struct avd_su_si_rel_tag { SaBoolT csi_add_rem; SaNameT comp_name; SaNameT csi_name; + bool absent; } AVD_SU_SI_REL; /* SusperSiRank table index structure */ diff --git a/osaf/services/saf/amf/amfd/ndfsm.cc b/osaf/services/saf/amf/amfd/ndfsm.cc --- a/osaf/services/saf/amf/amfd/ndfsm.cc +++ b/osaf/services/saf/amf/amfd/ndfsm.cc @@ -125,12 +125,14 @@ void avd_process_state_info_queue(AVD_CL } } - // Read cached rta from Imm + // Read cached rta from Imm, the order of calling + // below functions is IMPORTANT. // Reading sg must be after reading susi + // Cleanup compcsi must be after reading sg if (found_state_info == true) { - avd_compcsi_cleanup_imm_object(cb); avd_susi_read_headless_cached_rta(cb); avd_sg_read_headless_cached_rta(cb); + avd_compcsi_cleanup_imm_object(cb); avd_su_read_headless_cached_rta(cb); } done: diff --git a/osaf/services/saf/amf/amfd/sg.cc b/osaf/services/saf/amf/amfd/sg.cc --- a/osaf/services/saf/amf/amfd/sg.cc +++ b/osaf/services/saf/amf/amfd/sg.cc @@ -2133,6 +2133,23 @@ void avd_sg_read_headless_cached_rta(AVD } } } + + // Move fsm state of absent SUSI to AVD_SU_SI_STATE_ABSENT + for (const auto& su : sg->list_of_su) { + for (AVD_SU_SI_REL *susi = su->list_of_susi; susi; + susi = susi->su_next) { + TRACE("SUSI:'%s,%s', fsm:'%d'", Amf::to_string(&susi->su->name).c_str(), + Amf::to_string(&susi->si->name).c_str(), susi->fsm); + if (susi->absent == true) { + avd_susi_update_fsm(susi, AVD_SU_SI_STATE_ABSENT); + //Checkpoint to add this SUSI only after absent SUSI fsm + //moves to AVD_SU_SI_STATE_ABSENT, so var @absent is safe + //at standby side + m_AVSV_SEND_CKPT_UPDT_ASYNC_ADD(cb, susi, AVSV_CKPT_AVD_SI_ASS); + susi->absent = false; + } + } + } } } @@ -2142,6 +2159,31 @@ done: TRACE_LEAVE(); } +void AVD_SG::failover_absent_assignment() { + + TRACE_ENTER2("SG:'%s'", Amf::to_string(&name).c_str()); + for (const auto& su : list_of_su) { + if (su->any_susi_fsm_in(AVD_SU_SI_STATE_ABSENT)){ + node_fail(avd_cb, su); + break; + } + } + TRACE_LEAVE(); +} + +bool AVD_SG::any_assignment_absent() { + bool pending = false; + TRACE_ENTER2("SG:'%s'", Amf::to_string(&name).c_str()); + for (const auto& su : list_of_su) { + if (su->any_susi_fsm_in(AVD_SU_SI_STATE_ABSENT)){ + pending = true; + break; + } + } + TRACE_LEAVE(); + return pending; +} + bool AVD_SG::any_assignment_in_progress() { bool pending = false; TRACE_ENTER2("SG:'%s'", Amf::to_string(&name).c_str()); diff --git a/osaf/services/saf/amf/amfd/sg_2n_fsm.cc b/osaf/services/saf/amf/amfd/sg_2n_fsm.cc --- a/osaf/services/saf/amf/amfd/sg_2n_fsm.cc +++ b/osaf/services/saf/amf/amfd/sg_2n_fsm.cc @@ -75,6 +75,7 @@ static void complete_siswap(AVD_SU *su, AVD_SU_SI_STATE avd_su_fsm_state_determine(AVD_SU *su) { AVD_SU_SI_REL *temp_susi; bool assigning_flag = false, assigned_flag = false, modify_flag = false, unassingned_flag = false; + bool absent_flag = false; AVD_SU_SI_STATE fsm_state = AVD_SU_SI_STATE_ABSENT; TRACE_ENTER2("SU '%s'", su->name.value); @@ -98,16 +99,20 @@ AVD_SU_SI_STATE avd_su_fsm_state_determi } else if (AVD_SU_SI_STATE_ASGND == temp_susi->fsm) { assigned_flag = true; TRACE("Assigned su'%s', si'%s'", temp_susi->su->name.value, temp_susi->si->name.value); + } else if (AVD_SU_SI_STATE_ABSENT == temp_susi->fsm) { + absent_flag = true; + TRACE("Absent su'%s', si'%s'", temp_susi->su->name.value, temp_susi->si->name.value); } else { osafassert(0); } temp_susi = temp_susi->su_next; } - TRACE("assigning_flag'%u', unassingned_flag'%u', assigned_flag'%u', modify_flag'%u'", assigning_flag, - unassingned_flag, assigned_flag, modify_flag); - - if (true == modify_flag) { + TRACE("assigning_flag'%u', unassingned_flag'%u', assigned_flag'%u', modify_flag'%u', absent_flag'%u'", + assigning_flag, unassingned_flag, assigned_flag, modify_flag, absent_flag); + if (absent_flag == true) { + fsm_state = AVD_SU_SI_STATE_ABSENT; + } else if (true == modify_flag) { /* Rule 1. => If any one of the SUSI is Mod, then SU will be said to be modified. The other SUSI can be in assigning/assigned state in transition.*/ fsm_state = AVD_SU_SI_STATE_MODIFY; diff --git a/osaf/services/saf/amf/amfd/sgproc.cc b/osaf/services/saf/amf/amfd/sgproc.cc --- a/osaf/services/saf/amf/amfd/sgproc.cc +++ b/osaf/services/saf/amf/amfd/sgproc.cc @@ -709,8 +709,9 @@ void avd_su_oper_state_evh(AVD_CL_CB *cb (cluster_su_instantiation_done(cb, su) == true)) { avd_stop_tmr(cb, &cb->amf_init_tmr); - if (su->sg_of_su->any_assignment_in_progress() == false) { - su->sg_of_su->sg_fsm_state = AVD_SG_FSM_STABLE; + if (su->sg_of_su->any_assignment_in_progress() == false && + su->sg_of_su->any_assignment_absent() == false) { + su->sg_of_su->set_fsm_state(AVD_SG_FSM_STABLE); } cluster_startup_expiry_event_generate(cb); } @@ -872,8 +873,9 @@ void avd_su_oper_state_evh(AVD_CL_CB *cb /* if the SU is NCS SU, mark the SU readiness state as in service and call * the SG FSM. */ - if (su->sg_of_su->any_assignment_in_progress() == false) { - su->sg_of_su->sg_fsm_state = AVD_SG_FSM_STABLE; + if (su->sg_of_su->any_assignment_in_progress() == false && + su->sg_of_su->any_assignment_absent() == false) { + su->sg_of_su->set_fsm_state(AVD_SG_FSM_STABLE); } if (su->sg_of_su->sg_ncs_spec == true) { if (su->saAmfSUAdminState == SA_AMF_ADMIN_UNLOCKED) { @@ -1583,7 +1585,9 @@ void avd_su_si_assign_evh(AVD_CL_CB *cb, /* Free the messages */ avsv_dnd_msg_free(n2d_msg); evt->info.avnd_msg = nullptr; - + if (su != nullptr && su->sg_of_su->any_assignment_absent() == true) { + su->sg_of_su->failover_absent_assignment(); + } done: TRACE_LEAVE(); } @@ -2189,7 +2193,7 @@ uint32_t avd_sg_su_oper_list_del(AVD_CL_ TRACE_ENTER2("'%s'", su->name.value); if (su_oper_list.empty() == true) { - LOG_ER("%s: su_oper_list empty", __FUNCTION__); + LOG_WA("%s: su_oper_list empty", __FUNCTION__); goto done; } @@ -2244,6 +2248,12 @@ uint32_t avd_sg_su_si_mod_snd(AVD_CL_CB TRACE_ENTER2("'%s', state %u", su->name.value, state); + // No action on ABSENT SUSI + if (su->any_susi_fsm_in(AVD_SU_SI_STATE_ABSENT)) { + rc = NCSCC_RC_SUCCESS; + 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) { @@ -2353,6 +2363,12 @@ uint32_t avd_sg_su_si_del_snd(AVD_CL_CB TRACE_ENTER2("'%s'", su->name.value); + // No action on ABSENT SUSI + if (su->any_susi_fsm_in(AVD_SU_SI_STATE_ABSENT)) { + rc = NCSCC_RC_SUCCESS; + 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/osaf/services/saf/amf/amfd/siass.cc b/osaf/services/saf/amf/amfd/siass.cc --- a/osaf/services/saf/amf/amfd/siass.cc +++ b/osaf/services/saf/amf/amfd/siass.cc @@ -150,6 +150,10 @@ void avd_susi_update_fsm(AVD_SU_SI_REL * if (avd_cb->scs_absence_max_duration > 0) { avd_saImmOiRtObjectUpdate(&dn, const_cast<SaImmAttrNameT>("osafAmfSISUFsmState"), SA_IMM_ATTR_SAUINT32T, &susi->fsm); + // Need to write to IMM HA state, otherwise the ABSENT SUSI read from IMM + // will have wrong HA state, which lead to incorrect failover of ABSENT SUSI + avd_saImmOiRtObjectUpdate(&dn, const_cast<SaImmAttrNameT>("saAmfSISUHAState"), + SA_IMM_ATTR_SAUINT32T, &susi->state); } } TRACE_LEAVE(); @@ -168,7 +172,9 @@ void avd_susi_read_headless_cached_rta(A SaNameT dn, su_name, si_name; const SaImmAttrValuesT_2 **attributes; AVD_SU_SI_REL *susi = nullptr; + AVD_SU_SI_REL *absent_susi = nullptr; AVD_SU_SI_STATE imm_susi_fsm; + SaAmfHAStateT imm_ha_state; const char *className = "SaAmfSIAssignment"; const SaImmAttrNameT siass_attributes[] = { const_cast<SaImmAttrNameT>("safSISU"), @@ -209,7 +215,7 @@ void avd_susi_read_headless_cached_rta(A rc = immutil_getAttr("osafAmfSISUFsmState", attributes, 0, &imm_susi_fsm); osafassert(rc == SA_AIS_OK); - if (susi) { + if (susi) { // FOR PRESENT SUSI found in AMFND(s) TRACE("SISU:'%s', old(imm) fsm state: %d, new(sync) fsm state: %d", Amf::to_string(&dn).c_str(), imm_susi_fsm, susi->fsm); @@ -226,6 +232,7 @@ void avd_susi_read_headless_cached_rta(A // headless period. susi->fsm = imm_susi_fsm; #endif + //Checkpoint to add this SUSI m_AVSV_SEND_CKPT_UPDT_ASYNC_ADD(avd_cb, susi, AVSV_CKPT_AVD_SI_ASS); // restore assignment counter if (susi->fsm == AVD_SU_SI_STATE_ASGN || susi->fsm == AVD_SU_SI_STATE_ASGND || @@ -246,10 +253,33 @@ void avd_susi_read_headless_cached_rta(A } } - } else { - // This susi does not exist after headless, but it's still in IMM - // delete it for now - avd_saImmOiRtObjectDelete(&dn); + } else { // For ABSENT SUSI + if (su->sg_of_su->sg_ncs_spec == false) { + rc = immutil_getAttr("saAmfSISUHAState", attributes, 0, &imm_ha_state); + osafassert(rc == SA_AIS_OK); + TRACE("Absent SUSI, ha_state:'%u', fsm_state:'%u'", imm_ha_state, imm_susi_fsm); + if (imm_susi_fsm != AVD_SU_SI_STATE_UNASGN) { + absent_susi = avd_susi_create(avd_cb, si, su, imm_ha_state, false, AVSV_SUSI_ACT_BASE); + // Restore the fsm of this absent SUSI, which is used to determine + // whether a SU should be added in SG's SUOperationList + // Memorize it in temporary var @absent + // The fsm of this SUSI will be changed to AVD_SU_SI_STATE_ABSENT + // after restoring SUOperationList + absent_susi->fsm = imm_susi_fsm; + absent_susi->absent = true; + if (absent_susi->si->saAmfSIAdminState == SA_AMF_ADMIN_LOCKED || + absent_susi->si->saAmfSIAdminState == SA_AMF_ADMIN_SHUTTING_DOWN) { + if (absent_susi->fsm == AVD_SU_SI_STATE_MODIFY && + (absent_susi->state == SA_AMF_HA_QUIESCED || absent_susi->state == SA_AMF_HA_QUIESCING)) { + m_AVD_SET_SG_ADMIN_SI(cb, si); + } + } + } else { + avd_saImmOiRtObjectDelete(&dn); + } + } else { + avd_saImmOiRtObjectDelete(&dn); + } } } @@ -647,7 +677,11 @@ uint32_t avd_susi_mod_send(AVD_SU_SI_REL uint32_t rc = NCSCC_RC_SUCCESS; TRACE_ENTER2("SI '%s', SU '%s' ha_state:%d", susi->si->name.value, susi->su->name.value, ha_state); - + // No action on ABSENT SUSI + if (susi->fsm == AVD_SU_SI_STATE_ABSENT) { + rc = NCSCC_RC_SUCCESS; + goto done; + } old_state = susi->state; old_fsm_state = susi->fsm; susi->state = ha_state; @@ -688,7 +722,11 @@ uint32_t avd_susi_del_send(AVD_SU_SI_REL uint32_t rc = NCSCC_RC_SUCCESS; TRACE_ENTER2("SI '%s', SU '%s' ", susi->si->name.value, susi->su->name.value); - + // No action on ABSENT SUSI + if (susi->fsm == AVD_SU_SI_STATE_ABSENT) { + rc = NCSCC_RC_SUCCESS; + goto done; + } old_fsm_state = susi->fsm; avd_susi_update_fsm(susi, AVD_SU_SI_STATE_UNASGN); avd_snd_susi_msg(avd_cb, susi->su, susi, AVSV_SUSI_ACT_DEL, false, nullptr); diff --git a/osaf/services/saf/amf/amfd/su.cc b/osaf/services/saf/amf/amfd/su.cc --- a/osaf/services/saf/amf/amfd/su.cc +++ b/osaf/services/saf/amf/amfd/su.cc @@ -787,12 +787,17 @@ void AVD_SU::set_oper_state(SaAmfOperati * @param readiness_state */ void AVD_SU::set_readiness_state(SaAmfReadinessStateT readiness_state) { - if (saAmfSuReadinessState == readiness_state) + TRACE_ENTER2("'%s' current:'%s' -> new:'%s'", name.value, + avd_readiness_state_name[saAmfSuReadinessState], + avd_readiness_state_name[readiness_state]); + + if (saAmfSuReadinessState == readiness_state) { + TRACE_LEAVE(); return; + } osafassert(readiness_state <= SA_AMF_READINESS_STOPPING); - TRACE_ENTER2("'%s' %s", name.value, - avd_readiness_state_name[readiness_state]); + saflog(LOG_NOTICE, amfSvcUsrName, "%s ReadinessState %s => %s", name.value, avd_readiness_state_name[saAmfSuReadinessState], @@ -2360,14 +2365,16 @@ void AVD_SU::complete_admin_op(SaAisErro */ bool AVD_SU::any_susi_fsm_in(uint32_t check_fsm) { - TRACE_ENTER2("SU:'%s'", Amf::to_string(&name).c_str()); + TRACE_ENTER2("SU:'%s', check_fsm:'%d'", + Amf::to_string(&name).c_str(), check_fsm); bool rc = false; for (AVD_SU_SI_REL *susi = list_of_susi; susi && rc == false; susi = susi->su_next) { + TRACE("SUSI:'%s,%s', fsm:'%d'", Amf::to_string(&susi->su->name).c_str(), + Amf::to_string(&susi->si->name).c_str(), susi->fsm); if (susi->fsm == check_fsm) { rc = true; - TRACE("SUSI:'%s,%s', fsm:'%d'", Amf::to_string(&susi->su->name).c_str(), - Amf::to_string(&susi->si->name).c_str(), susi->fsm); + TRACE("Found"); } } TRACE_LEAVE(); ------------------------------------------------------------------------------ _______________________________________________ Opensaf-devel mailing list Opensaf-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/opensaf-devel