osaf/services/saf/amf/amfd/cluster.cc | 69 ++++-
osaf/services/saf/amf/amfd/comp.cc | 8 +-
osaf/services/saf/amf/amfd/csi.cc | 107 +++++++
osaf/services/saf/amf/amfd/imm.cc | 58 ++++
osaf/services/saf/amf/amfd/include/cb.h | 5 +
osaf/services/saf/amf/amfd/include/cluster.h | 1 +
osaf/services/saf/amf/amfd/include/csi.h | 2 +
osaf/services/saf/amf/amfd/include/db_template.h | 1 +
osaf/services/saf/amf/amfd/include/evt.h | 3 +
osaf/services/saf/amf/amfd/include/mds.h | 7 +-
osaf/services/saf/amf/amfd/include/msg.h | 2 +-
osaf/services/saf/amf/amfd/include/node.h | 3 +
osaf/services/saf/amf/amfd/include/proc.h | 7 +
osaf/services/saf/amf/amfd/include/sg.h | 16 +-
osaf/services/saf/amf/amfd/include/si.h | 1 +
osaf/services/saf/amf/amfd/include/susi.h | 3 +
osaf/services/saf/amf/amfd/include/timer.h | 1 +
osaf/services/saf/amf/amfd/include/util.h | 2 +-
osaf/services/saf/amf/amfd/main.cc | 24 +
osaf/services/saf/amf/amfd/mds.cc | 4 +-
osaf/services/saf/amf/amfd/ndfsm.cc | 325 ++++++++++++++++++++++-
osaf/services/saf/amf/amfd/ndmsg.cc | 18 +-
osaf/services/saf/amf/amfd/ndproc.cc | 103 +++++++-
osaf/services/saf/amf/amfd/node.cc | 9 +-
osaf/services/saf/amf/amfd/sg.cc | 57 ++++
osaf/services/saf/amf/amfd/sg_2n_fsm.cc | 140 +++++++++
osaf/services/saf/amf/amfd/sg_nored_fsm.cc | 6 +
osaf/services/saf/amf/amfd/sg_npm_fsm.cc | 24 +
osaf/services/saf/amf/amfd/sg_nway_fsm.cc | 24 +
osaf/services/saf/amf/amfd/sg_nwayact_fsm.cc | 6 +
osaf/services/saf/amf/amfd/sgproc.cc | 49 ++-
osaf/services/saf/amf/amfd/si.cc | 45 ++-
osaf/services/saf/amf/amfd/siass.cc | 123 ++++++++
osaf/services/saf/amf/amfd/su.cc | 19 +-
34 files changed, 1209 insertions(+), 63 deletions(-)
Outlined changes:
. node_up_msg event handling has changed so that amfd can collect
the sync information sent from amfnd
. Node Sync timer is introduced as a window of amfnd sync from headless
. Failover may happens during headless, adjust_delayed_failover() to
balance the assignment in term of active/standby availability
. SI dependencies also can change due to assignment removal during headless
adjust_delayed_sidep() to update the si dependencies
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
@@ -25,6 +25,7 @@
#include <imm.h>
#include <evt.h>
#include <proc.h>
+#include <si_dep.h>
/* Singleton cluster object */
static AVD_CLUSTER _avd_cluster;
@@ -52,6 +53,7 @@ AVD_CLUSTER *avd_cluster = &_avd_cluster
void avd_cluster_tmr_init_evh(AVD_CL_CB *cb, AVD_EVT *evt)
{
TRACE_ENTER();
+ AVD_SU *su = nullptr;
saflog(LOG_NOTICE, amfSvcUsrName, "Cluster startup timeout, assigning
SIs to SUs");
osafassert(evt->info.tmr.type == AVD_TMR_CL_INIT);
@@ -74,19 +76,84 @@ void avd_cluster_tmr_init_evh(AVD_CL_CB
* system that are not NCS specific.
*/
+ /* The SI Dependency could be broken due to failover or instantiation/
+ * termination failure during headless.
+ * adjust_delayed_sidep() removes SI(s) assignment which has any
+ * unassigned sponsored SI.
+ *
+ */
+ if (cb->scs_absence_max_duration > 0) {
+ adjust_delayed_sidep();
+ }
+
for (std::map<std::string, AVD_SG*>::const_iterator it = sg_db->begin();
it != sg_db->end(); it++) {
AVD_SG *i_sg = it->second;
if ((i_sg->list_of_su.empty() == true) || (i_sg->sg_ncs_spec ==
true)) {
continue;
}
- i_sg->realign(cb, i_sg);
+
+ /* If hydra is enabled and su failover happened during headless,
+ * currently only the active assignment is removed but the
standby
+ * assignment has not been switched to active.
+ * adjust_delayed_failover() finds the standby assignment being
+ * moved to active.
+ * Next, the realign() will find the remaining possible su-si
+ * to satisfy the number of assignment configuration.
+ */
+ if (cb->scs_absence_max_duration > 0) {
+ i_sg->adjust_delayed_failover(cb);
+ }
+ if (i_sg->sg_fsm_state == AVD_SG_FSM_STABLE)
+ i_sg->realign(cb, i_sg);
+ }
+
+ if (cb->scs_absence_max_duration > 0) {
+ TRACE("check if any SU is auto repair enabled");
+
+ for (std::map<std::string, AVD_SU*>::const_iterator it =
su_db->begin();
+ it != su_db->end(); it++) {
+
+ su = it->second;
+
+ if (su->list_of_susi == nullptr &&
+ su->su_on_node != nullptr &&
+ su->su_on_node->saAmfNodeOperState ==
SA_AMF_OPERATIONAL_ENABLED) {
+ su_try_repair(su);
+ }
+ }
}
done:
TRACE_LEAVE();
}
+/****************************************************************************
+ * Name : avd_node_sync_tmr_evh
+ *
+ * Description : This is node sync timer expiry routine handler
+ *
+ * Arguments : cb - AvD cb
+ * evt - ptr to the received event
+ *
+ * Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
+ *
+ * Notes : None.
+ ***************************************************************************/
+void avd_node_sync_tmr_evh(AVD_CL_CB *cb, AVD_EVT *evt)
+{
+ TRACE_ENTER();
+
+ osafassert(evt->info.tmr.type == AVD_TMR_NODE_SYNC);
+ LOG_NO("NodeSync timeout");
+
+ // Setting true here to indicate the node sync window has closed
+ // Further node up message will be treated specially
+ cb->node_sync_window_closed = true;
+
+ TRACE_LEAVE();
+}
+
static void ccb_apply_modify_hdlr(struct CcbUtilOperationData *opdata)
{
const SaImmAttrModificationT_2 *attr_mod;
diff --git a/osaf/services/saf/amf/amfd/comp.cc
b/osaf/services/saf/amf/amfd/comp.cc
--- a/osaf/services/saf/amf/amfd/comp.cc
+++ b/osaf/services/saf/amf/amfd/comp.cc
@@ -161,7 +161,13 @@ void avd_comp_pres_state_set(AVD_COMP *c
node->name.value);
LOG_NO("Node Failfast for '%s' as '%s' enters Term/Inst Failed
state",
node->name.value,comp->comp_info.name.value);
- avd_d2n_reboot_snd(node);
+
+ if (node->node_state < AVD_AVND_STATE_PRESENT) {
+ // reboot when node_up is processed
+ node->reboot = true;
+ } else {
+ avd_d2n_reboot_snd(node);
+ }
}
TRACE_LEAVE();
}
diff --git a/osaf/services/saf/amf/amfd/csi.cc
b/osaf/services/saf/amf/amfd/csi.cc
--- a/osaf/services/saf/amf/amfd/csi.cc
+++ b/osaf/services/saf/amf/amfd/csi.cc
@@ -1409,3 +1409,110 @@ bool are_sponsor_csis_assigned_in_su(AVD
return true;
}
+/**
+ * Clean up COMPCSI objects by searching for SaAmfCSIAssignment instances in
IMM
+ * @return SA_AIS_OK when OK
+ */
+SaAisErrorT avd_compcsi_cleanup(void)
+{
+ SaAisErrorT rc;
+ SaImmSearchHandleT searchHandle;
+ SaImmSearchParametersT_2 searchParam;
+ const char *className = "SaAmfCSIAssignment";
+
+ TRACE_ENTER();
+
+ searchParam.searchOneAttr.attrName =
const_cast<SaImmAttrNameT>("SaImmAttrClassName");
+ searchParam.searchOneAttr.attrValueType = SA_IMM_ATTR_SASTRINGT;
+ searchParam.searchOneAttr.attrValue = &className;
+
+ if ((rc = immutil_saImmOmSearchInitialize_2(avd_cb->immOmHandle,
nullptr, SA_IMM_SUBTREE,
+ SA_IMM_SEARCH_ONE_ATTR | SA_IMM_SEARCH_GET_NO_ATTR, &searchParam,
+ nullptr, &searchHandle)) != SA_AIS_OK) {
+ LOG_ER("%s: saImmOmSearchInitialize_2 failed: %u",
__FUNCTION__, rc);
+ goto done;
+ }
+
+ SaNameT csiass_name;
+ const SaImmAttrValuesT_2 **attributes;
+ while ((rc = immutil_saImmOmSearchNext_2(searchHandle, &csiass_name,
+ (SaImmAttrValuesT_2 ***)&attributes)) ==
SA_AIS_OK) {
+ avd_saImmOiRtObjectDelete(&csiass_name);
+ }
+
+ (void)immutil_saImmOmSearchFinalize(searchHandle);
+
+done:
+ TRACE_LEAVE();
+ return SA_AIS_OK;
+}
+
+/**
+ * Re-create csi assignment and update comp related states, which are
+ * collected after headless
+ * Update relevant runtime attributes
+ * @return SA_AIS_OK when OK
+ */
+SaAisErrorT avd_compcsi_recreate(AVSV_N2D_ND_CSICOMP_STATE_MSG_INFO *info)
+{
+ AVD_SU_SI_REL *susi;
+ const AVD_SI *si;
+ AVD_CSI *csi;
+ AVD_COMP *comp;
+ const AVSV_CSICOMP_STATE_MSG *csicomp;
+ const AVSV_COMP_STATE_MSG *comp_state;
+
+ TRACE_ENTER();
+
+ for (csicomp = info->csicomp_list; csicomp != nullptr;
csicomp=csicomp->next) {
+ csi = csi_db->find(Amf::to_string(&csicomp->safCSI));
+ osafassert(csi);
+
+ comp = comp_db->find(Amf::to_string(&csicomp->safComp));
+ osafassert(comp);
+
+ TRACE("Received CSICOMP state msg: csi %s, comp %s",
+ (char*)&csicomp->safCSI.value,
(char*)&csicomp->safComp.value);
+
+ si = csi->si;
+ osafassert(si);
+
+ susi = avd_susi_find(avd_cb, &comp->su->name, &si->name);
+ if (susi == 0) {
+ LOG_ER("SU_SI_REL record for SU '%s' and SI '%s' was
not found",
+ comp->su->name.value, si->name.value);
+ return SA_AIS_ERR_NOT_EXIST;
+ }
+
+ AVD_COMP_CSI_REL *compcsi = avd_compcsi_create(susi, csi, comp,
true);
+ osafassert(compcsi);
+ }
+
+ for (comp_state = info->comp_list; comp_state != nullptr; comp_state =
comp_state->next) {
+ comp = comp_db->find(Amf::to_string(&comp_state->safComp));
+ osafassert(comp);
+
+ // operation state
+ avd_comp_oper_state_set(comp,
+
static_cast<SaAmfOperationalStateT>(comp_state->comp_oper_state));
+
+ // . update saAmfCompReadinessState after
SU:saAmfSuReadinessState
+ // . saAmfCompCurrProxyName and saAmfCompCurrProxiedNames
wouldn't change during headless
+ // so they need not to update
+
+ // presense state
+ avd_comp_pres_state_set(comp,
+
static_cast<SaAmfPresenceStateT>(comp_state->comp_pres_state));
+
+ // restart count
+ comp->saAmfCompRestartCount = comp_state->comp_restart_cnt;
+ m_AVSV_SEND_CKPT_UPDT_ASYNC_UPDT(avd_cb, comp,
AVSV_CKPT_COMP_RESTART_COUNT);
+ avd_saImmOiRtObjectUpdate(&comp->comp_info.name,
+ const_cast<SaImmAttrNameT>("saAmfCompRestartCount"),
SA_IMM_ATTR_SAUINT32T,
+ &comp->saAmfCompRestartCount);
+ }
+
+ TRACE_LEAVE();
+ return SA_AIS_OK;
+}
+
diff --git a/osaf/services/saf/amf/amfd/imm.cc
b/osaf/services/saf/amf/amfd/imm.cc
--- a/osaf/services/saf/amf/amfd/imm.cc
+++ b/osaf/services/saf/amf/amfd/imm.cc
@@ -1245,6 +1245,60 @@ static const SaImmOiCallbacksT_2 avd_cal
};
/*****************************************************************************
+ * Function: hydra_config_get
+ *
+ * Purpose: This function checks if Hydra configuration is enabled in IMM
+ * then set the corresponding value to scs_absence_max_duration
variable in
+ * avd_cb.
+ *
+ * Input: None.
+ *
+ * Returns: SaAisErrorT
+ *
+ * NOTES: If IMM attribute fetching fails that means Hydra
+ * configuration is disabled.
+ *
+ **************************************************************************/
+static SaAisErrorT hydra_config_get(void)
+{
+ SaAisErrorT rc = SA_AIS_OK;
+ const SaImmAttrValuesT_2 **attributes;
+ SaImmAccessorHandleT accessorHandle;
+ SaNameT dn = {0, "opensafImm=opensafImm,safApp=safImmService"};
+ SaImmAttrNameT attrName =
const_cast<SaImmAttrNameT>("scAbsenceAllowed");
+ SaImmAttrNameT attributeNames[] = {attrName, nullptr};
+ const SaUint32T *value = nullptr;
+
+ TRACE_ENTER();
+
+ dn.length = strlen((char *)dn.value);
+
+ immutil_saImmOmAccessorInitialize(avd_cb->immOmHandle, &accessorHandle);
+ rc = immutil_saImmOmAccessorGet_2(accessorHandle, &dn, attributeNames,
+ (SaImmAttrValuesT_2 ***)&attributes);
+
+ if (rc != SA_AIS_OK) {
+ LOG_WA("saImmOmAccessorGet_2 FAILED %u for %s", rc, dn.value);
+ goto done;
+ }
+
+ value = immutil_getUint32Attr(attributes, attrName, 0);
+ if (value == nullptr) {
+ LOG_WA("immutil_getUint32Attr FAILED for %s", dn.value);
+ goto done;
+ }
+
+ avd_cb->scs_absence_max_duration = *value;
+
+done:
+ immutil_saImmOmAccessorFinalize(accessorHandle);
+ LOG_IN("scs_absence_max_duration: %d",
avd_cb->scs_absence_max_duration);
+
+ TRACE_LEAVE();
+ return SA_AIS_OK;
+}
+
+/*****************************************************************************
* Function: avd_imm_init
*
* Purpose: This function Initialize the OI interface and get a selection
@@ -1501,6 +1555,10 @@ unsigned int avd_imm_config_get(void)
if (avd_sidep_config_get() != SA_AIS_OK)
goto done;
+ /* retrieve hydra configuration from IMM */
+ if (hydra_config_get() != SA_AIS_OK)
+ goto done;
+
// SGs needs to adjust configuration once all instances have been added
{
for (std::map<std::string, AVD_SG*>::const_iterator it =
sg_db->begin();
diff --git a/osaf/services/saf/amf/amfd/include/cb.h
b/osaf/services/saf/amf/amfd/include/cb.h
--- a/osaf/services/saf/amf/amfd/include/cb.h
+++ b/osaf/services/saf/amf/amfd/include/cb.h
@@ -182,6 +182,7 @@ typedef struct cl_cb_tag {
SaClmNodeIdT node_avd_failed; /* node id where AVD is down */
AVD_TMR amf_init_tmr; /* The timer for amf initialisation. */
+ AVD_TMR node_sync_tmr; /* The timer for reception of all node_up from
all PLs. */
AVD_TMR heartbeat_tmr; /* The timer for sending heart beats to nd. */
SaTimeT heartbeat_tmr_period;
@@ -215,6 +216,8 @@ typedef struct cl_cb_tag {
* Used to skip usage of dependent services in the no-active state
*/
bool active_services_exist;
+ bool all_nodes_synced;
+ bool node_sync_window_closed;
/*
A list of those SIs for which SI dep tolerance timer is running.
@@ -228,6 +231,8 @@ typedef struct cl_cb_tag {
*/
std::list<AVD_SI*> sis_in_Tolerance_Timer_state;
+ /* The duration that amfd should tolerate the absence of SCs */
+ uint32_t scs_absence_max_duration;
} AVD_CL_CB;
extern AVD_CL_CB *avd_cb;
diff --git a/osaf/services/saf/amf/amfd/include/cluster.h
b/osaf/services/saf/amf/amfd/include/cluster.h
--- a/osaf/services/saf/amf/amfd/include/cluster.h
+++ b/osaf/services/saf/amf/amfd/include/cluster.h
@@ -38,6 +38,7 @@ extern AVD_CLUSTER *avd_cluster;
extern SaAisErrorT avd_cluster_config_get(void);
extern void avd_cluster_tmr_init_evh(AVD_CL_CB *cb, struct avd_evt_tag *evt);
+extern void avd_node_sync_tmr_evh(AVD_CL_CB *cb, struct avd_evt_tag *evt);
extern void avd_cluster_constructor(void);
#endif
diff --git a/osaf/services/saf/amf/amfd/include/csi.h
b/osaf/services/saf/amf/amfd/include/csi.h
--- a/osaf/services/saf/amf/amfd/include/csi.h
+++ b/osaf/services/saf/amf/amfd/include/csi.h
@@ -184,5 +184,7 @@ extern AVD_CSI *csi_create(const SaNameT
extern bool csi_assignment_validate(AVD_SG *sg);
extern SaAisErrorT csi_assign_hdlr(AVD_CSI *csi);
extern bool are_sponsor_csis_assigned_in_su(AVD_CSI *dep_csi, AVD_SU *su);
+SaAisErrorT avd_compcsi_cleanup(void);
+SaAisErrorT avd_compcsi_recreate(AVSV_N2D_ND_CSICOMP_STATE_MSG_INFO *info);
#endif
diff --git a/osaf/services/saf/amf/amfd/include/db_template.h
b/osaf/services/saf/amf/amfd/include/db_template.h
--- a/osaf/services/saf/amf/amfd/include/db_template.h
+++ b/osaf/services/saf/amf/amfd/include/db_template.h
@@ -44,6 +44,7 @@ class AmfDb {
const_iterator begin() const {return db.begin();}
const_iterator end() const {return db.end();}
+ unsigned int size() const {return db.size();}
const_reverse_iterator rbegin() const {return db.rbegin();}
const_reverse_iterator rend() const {return db.rend();}
diff --git a/osaf/services/saf/amf/amfd/include/evt.h
b/osaf/services/saf/amf/amfd/include/evt.h
--- a/osaf/services/saf/amf/amfd/include/evt.h
+++ b/osaf/services/saf/amf/amfd/include/evt.h
@@ -51,10 +51,13 @@ typedef enum avd_evt_type {
AVD_EVT_SHUTDOWN_APP_SU_MSG,
AVD_EVT_VERIFY_ACK_NACK_MSG,
AVD_EVT_COMP_VALIDATION_MSG,
+ AVD_EVT_ND_SISU_STATE_INFO_MSG,
+ AVD_EVT_ND_CSICOMP_STATE_INFO_MSG,
AVD_EVT_MSG_MAX,
AVD_EVT_TMR_SND_HB = AVD_EVT_MSG_MAX,
AVD_EVT_TMR_CL_INIT,
AVD_EVT_TMR_SI_DEP_TOL,
+ AVD_EVT_TMR_NODE_SYNC,
AVD_EVT_TMR_MAX,
AVD_EVT_MDS_AVD_UP = AVD_EVT_TMR_MAX,
AVD_EVT_MDS_AVD_DOWN,
diff --git a/osaf/services/saf/amf/amfd/include/mds.h
b/osaf/services/saf/amf/amfd/include/mds.h
--- a/osaf/services/saf/amf/amfd/include/mds.h
+++ b/osaf/services/saf/amf/amfd/include/mds.h
@@ -33,13 +33,13 @@
/* In Service upgrade support */
#define AVD_MDS_SUB_PART_VERSION_4 4
-#define AVD_MDS_SUB_PART_VERSION 5
+#define AVD_MDS_SUB_PART_VERSION 6
#define AVD_AVND_SUBPART_VER_MIN 1
-#define AVD_AVND_SUBPART_VER_MAX 5
+#define AVD_AVND_SUBPART_VER_MAX 6
#define AVD_AVD_SUBPART_VER_MIN 1
-#define AVD_AVD_SUBPART_VER_MAX 5
+#define AVD_AVD_SUBPART_VER_MAX 6
/* Message format versions */
#define AVD_AVD_MSG_FMT_VER_1 1
@@ -47,6 +47,7 @@
#define AVD_AVD_MSG_FMT_VER_3 3
#define AVD_AVD_MSG_FMT_VER_4 4
#define AVD_AVD_MSG_FMT_VER_5 5
+#define AVD_AVD_MSG_FMT_VER_6 6
uint32_t avd_mds_set_vdest_role(struct cl_cb_tag *cb, SaAmfHAStateT role);
uint32_t avd_mds_init(struct cl_cb_tag *cb);
diff --git a/osaf/services/saf/amf/amfd/include/msg.h
b/osaf/services/saf/amf/amfd/include/msg.h
--- a/osaf/services/saf/amf/amfd/include/msg.h
+++ b/osaf/services/saf/amf/amfd/include/msg.h
@@ -37,7 +37,7 @@
#include <amf_d2nmsg.h>
typedef enum {
- AVD_D2D_CHANGE_ROLE_REQ = AVSV_DND_MSG_MAX,
+ AVD_D2D_CHANGE_ROLE_REQ = AVSV_D2D_CHANGE_ROLE_REQ,
AVD_D2D_CHANGE_ROLE_RSP,
AVD_D2D_MSG_MAX,
} AVD_D2D_MSG_TYPE;
diff --git a/osaf/services/saf/amf/amfd/include/node.h
b/osaf/services/saf/amf/amfd/include/node.h
--- a/osaf/services/saf/amf/amfd/include/node.h
+++ b/osaf/services/saf/amf/amfd/include/node.h
@@ -144,6 +144,8 @@ class AVD_AVND {
bool clm_change_start_preceded; /* to indicate there was CLM start cbk
before CLM completed cb. */
bool recvr_fail_sw; /* to indicate there was node reboot because of node
failover/switchover.*/
AVD_AMF_NG *admin_ng; /* points to the nodegroup on which admin operation is
going on.*/
+ uint16_t node_up_msg_count; /* to count of node_up msg that director had
received from this node */
+ bool reboot;
private:
void initialize();
// disallow copy and assign
@@ -206,6 +208,7 @@ extern AVD_AVND *avd_node_getnext(const
extern uint32_t avd_node_add_nodeid(AVD_AVND *avnd);
extern void avd_node_delete_nodeid(AVD_AVND *node);
extern AVD_AVND *avd_node_find_nodeid(SaClmNodeIdT node_id);
+extern AVD_AVND *avd_node_get(const SaNameT *dn);
extern SaAisErrorT avd_node_config_get(void);
extern void avd_node_state_set(AVD_AVND *node, AVD_AVND_STATE node_state);
extern void avd_node_oper_state_set(AVD_AVND *node, SaAmfOperationalStateT
oper_state);
diff --git a/osaf/services/saf/amf/amfd/include/proc.h
b/osaf/services/saf/amf/amfd/include/proc.h
--- a/osaf/services/saf/amf/amfd/include/proc.h
+++ b/osaf/services/saf/amf/amfd/include/proc.h
@@ -43,6 +43,7 @@ void avd_su_oper_state_evh(AVD_CL_CB *cb
void avd_su_si_assign_evh(AVD_CL_CB *cb, struct avd_evt_tag *evt);
uint32_t avd_new_assgn_susi(AVD_CL_CB *cb, AVD_SU *su, AVD_SI *si,
SaAmfHAStateT role, bool ckpt, AVD_SU_SI_REL
**ret_ptr);
+void su_try_repair(const AVD_SU *su);
void avd_sg_app_node_su_inst_func(AVD_CL_CB *cb, AVD_AVND *avnd);
uint32_t avd_sg_app_su_inst_func(AVD_CL_CB *cb, AVD_SG *sg);
uint32_t avd_sg_su_oper_list_add(AVD_CL_CB *cb, AVD_SU *su, bool ckpt);
@@ -58,6 +59,10 @@ uint32_t avd_sg_nway_si_assign(AVD_CL_CB
/* The following are for N-way Active redundancy model */
AVD_SU *avd_sg_nacvred_su_chose_asgn(AVD_CL_CB *cb, AVD_SG *sg);
+uint32_t avd_count_node_up(AVD_CL_CB *cb);
+uint32_t avd_evt_queue_count(AVD_CL_CB *cb);
+uint32_t avd_count_sync_node_size(AVD_CL_CB *cb);
+void avd_process_state_info_queue(AVD_CL_CB *cb);
void avd_node_up_evh(AVD_CL_CB *cb, struct avd_evt_tag *evt);
void avd_reg_su_evh(AVD_CL_CB *cb, struct avd_evt_tag *evt);
void avd_oper_req_evh(AVD_CL_CB *cb, struct avd_evt_tag *evt);
@@ -72,6 +77,8 @@ void avd_mds_qsd_role_evh(AVD_CL_CB *cb,
void avd_node_down_appl_susi_failover(AVD_CL_CB *cb, AVD_AVND *avnd);
void avd_node_down_mw_susi_failover(AVD_CL_CB *cb, AVD_AVND *avnd);
void avd_node_down_func(AVD_CL_CB *cb, AVD_AVND *avnd);
+void avd_nd_sisu_state_info_evh(AVD_CL_CB *cb, struct avd_evt_tag *evt);
+void avd_nd_compcsi_state_info_evh(AVD_CL_CB *cb, struct avd_evt_tag *evt);
uint32_t avd_node_down(AVD_CL_CB *cb, SaClmNodeIdT node_id);
AVD_AVND *avd_msg_sanity_chk(AVD_EVT *evt, SaClmNodeIdT node_id,
AVSV_DND_MSG_TYPE msg_typ, uint32_t msg_id);
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
@@ -288,6 +288,15 @@ public:
virtual void node_fail(AVD_CL_CB *cb, AVD_SU *su) = 0;
/**
+ * Run the delayed su failover that happened during headless
+ * Called when cluster init finishes and hydra option is enabled
+ *
+ * @param cb
+ * @return
+ */
+ virtual void adjust_delayed_failover(AVD_CL_CB *cb) = 0;
+
+ /**
* Handle SG realign
* Assign SIs if needed. If any assigning is gets done it adds
* the SUs to the operation list and sets the SG FSM state to SG
realign.
@@ -439,6 +448,7 @@ class SG_2N : public AVD_SG {
public:
~SG_2N();
void node_fail(AVD_CL_CB*, AVD_SU*);
+ void adjust_delayed_failover(AVD_CL_CB *cb);
uint32_t realign(AVD_CL_CB *cb, AVD_SG *sg);
uint32_t si_assign(AVD_CL_CB *cb, AVD_SI *si);
uint32_t si_admin_down(AVD_CL_CB *cb, AVD_SI *si);
@@ -472,6 +482,7 @@ class SG_NORED : public AVD_SG {
public:
~SG_NORED();
void node_fail(AVD_CL_CB*, AVD_SU*);
+ void adjust_delayed_failover(AVD_CL_CB *cb);
uint32_t realign(AVD_CL_CB *cb, AVD_SG *sg);
uint32_t si_assign(AVD_CL_CB *cb, AVD_SI *si);
uint32_t si_admin_down(AVD_CL_CB *cb, AVD_SI *si);
@@ -495,6 +506,7 @@ class SG_NPM : public AVD_SG {
public:
~SG_NPM();
void node_fail(AVD_CL_CB*, AVD_SU*);
+ void adjust_delayed_failover(AVD_CL_CB *cb);
uint32_t realign(AVD_CL_CB *cb, AVD_SG *sg);
uint32_t si_assign(AVD_CL_CB *cb, AVD_SI *si);
uint32_t si_admin_down(AVD_CL_CB *cb, AVD_SI *si);
@@ -526,6 +538,7 @@ class SG_NACV : public AVD_SG {
public:
~SG_NACV();
void node_fail(AVD_CL_CB*, AVD_SU*);
+ void adjust_delayed_failover(AVD_CL_CB *cb);
uint32_t realign(AVD_CL_CB *cb, AVD_SG *sg);
uint32_t si_assign(AVD_CL_CB *cb, AVD_SI *si);
uint32_t si_admin_down(AVD_CL_CB *cb, AVD_SI *si);
@@ -547,6 +560,7 @@ class SG_NWAY : public AVD_SG {
public:
~SG_NWAY();
void node_fail(AVD_CL_CB*, AVD_SU*);
+ void adjust_delayed_failover(AVD_CL_CB *cb);
uint32_t realign(AVD_CL_CB *cb, AVD_SG *sg);
uint32_t si_assign(AVD_CL_CB *cb, AVD_SI *si);
uint32_t si_admin_down(AVD_CL_CB *cb, AVD_SI *si);
@@ -592,6 +606,6 @@ extern void avd_sg_adjust_config(AVD_SG
extern uint32_t sg_instantiated_su_count(const AVD_SG *sg);
extern bool sg_stable_after_lock_in_or_unlock_in(AVD_SG *sg);
extern void process_su_si_response_for_ng(AVD_SU *su, SaAisErrorT res);
-
+extern void adjust_delayed_sidep(void);
#endif
diff --git a/osaf/services/saf/amf/amfd/include/si.h
b/osaf/services/saf/amf/amfd/include/si.h
--- a/osaf/services/saf/amf/amfd/include/si.h
+++ b/osaf/services/saf/amf/amfd/include/si.h
@@ -139,6 +139,7 @@ public:
void arrange_dep_csi(AVD_CSI* csi);
void add_csi_db(AVD_CSI* csi);
bool is_sirank_valid(uint32_t newSiRank) const;
+ void update_alarm_state(bool alarm_state, bool sent_notification =
true);
void update_sirank(uint32_t newSiRank);
bool si_dep_states_check();
private:
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
@@ -157,4 +157,7 @@ extern bool si_assignment_state_check(AV
extern SaAmfHAStateT avd_su_state_determine(AVD_SU *su);
extern AVD_SU_SI_REL *avd_siass_next_susi_to_quiesce(const AVD_SU_SI_REL
*susi);
extern bool avd_susi_quiesced_canbe_given(const AVD_SU_SI_REL *susi);
+SaAisErrorT avd_susi_cleanup(void);
+SaAisErrorT avd_susi_recreate(AVSV_N2D_ND_SISU_STATE_MSG_INFO*);
+
#endif
diff --git a/osaf/services/saf/amf/amfd/include/timer.h
b/osaf/services/saf/amf/amfd/include/timer.h
--- a/osaf/services/saf/amf/amfd/include/timer.h
+++ b/osaf/services/saf/amf/amfd/include/timer.h
@@ -44,6 +44,7 @@ typedef enum avd_tmr_type {
* SIs to application SU. */
AVD_TMR_SI_DEP_TOL, /* SI_SI dependency tolerance timer */
+ AVD_TMR_NODE_SYNC, /* node sync timer for all PLs from headless */
AVD_TMR_MAX
} AVD_TMR_TYPE;
diff --git a/osaf/services/saf/amf/amfd/include/util.h
b/osaf/services/saf/amf/amfd/include/util.h
--- a/osaf/services/saf/amf/amfd/include/util.h
+++ b/osaf/services/saf/amf/amfd/include/util.h
@@ -44,7 +44,7 @@
class AVD_SU;
typedef enum {
- AVD_D2D_CHANGE_ROLE_REQ = AVSV_DND_MSG_MAX,
+ AVD_D2D_CHANGE_ROLE_REQ = AVSV_D2D_CHANGE_ROLE_REQ,
AVD_D2D_CHANGE_ROLE_RSP,
AVD_D2D_MSG_MAX,
} AVD_D2D_MSG_TYPE;
diff --git a/osaf/services/saf/amf/amfd/main.cc
b/osaf/services/saf/amf/amfd/main.cc
--- a/osaf/services/saf/amf/amfd/main.cc
+++ b/osaf/services/saf/amf/amfd/main.cc
@@ -100,11 +100,14 @@ static const AVD_EVT_HDLR g_actv_list[AV
invalid_evh, /* AVD_EVT_SHUTDOWN_APP_SU_MSG */
avd_ack_nack_evh, /* AVD_EVT_VERIFY_ACK_NACK_MSG */
avd_comp_validation_evh, /* AVD_EVT_COMP_VALIDATION_MSG */
+ avd_nd_sisu_state_info_evh, /* AVD_EVT_ND_SISU_STATE_INFO_MSG */
+ avd_nd_compcsi_state_info_evh, /* AVD_EVT_ND_COMPCSI_STATE_INFO_MSG
*/
/* active AvD timer events processing */
avd_tmr_snd_hb_evh, /* AVD_EVT_TMR_SND_HB */
avd_cluster_tmr_init_evh, /* AVD_EVT_TMR_CL_INIT */
avd_sidep_tol_tmr_evh, /* AVD_EVT_TMR_SI_DEP_TOL */
+ avd_node_sync_tmr_evh, /* AVD_EVT_TMR_ALL_NODE_UP */
/* active AvD MDS events processing */
avd_mds_avd_up_evh, /* AVD_EVT_MDS_AVD_UP */
@@ -139,11 +142,15 @@ static const AVD_EVT_HDLR g_stndby_list[
standby_invalid_evh, /* AVD_EVT_SHUTDOWN_APP_SU_MSG */
standby_invalid_evh, /* AVD_EVT_VERIFY_ACK_NACK_MSG */
standby_invalid_evh, /* AVD_EVT_COMP_VALIDATION_MSG */
+ standby_invalid_evh, /* AVD_EVT_ND_SUSI_STATE_INFO_MSG */
+ standby_invalid_evh, /* AVD_EVT_ND_COMPCSI_STATE_INFO_MSG */
+
/* standby AvD timer events processing */
avd_tmr_snd_hb_evh, /* AVD_EVT_TMR_SND_HB */
standby_invalid_evh, /* AVD_EVT_TMR_CL_INIT */
avd_sidep_tol_tmr_evh, /* AVD_EVT_TMR_SI_DEP_TOL */
+ standby_invalid_evh, /* AVD_EVT_TMR_ALL_NODE_UP */
/* standby AvD MDS events processing */
avd_mds_avd_up_evh, /* AVD_EVT_MDS_AVD_UP */
@@ -177,11 +184,14 @@ static const AVD_EVT_HDLR g_quiesc_list[
invalid_evh, /* AVD_EVT_SHUTDOWN_APP_SU_MSG */
qsd_invalid_evh, /* AVD_EVT_VERIFY_ACK_NACK_MSG */
avd_comp_validation_evh, /* AVD_EVT_COMP_VALIDATION_MSG */
+ qsd_invalid_evh, /* AVD_EVT_ND_SISU_STATE_INFO_MSG */
+ qsd_invalid_evh, /* AVD_EVT_ND_COMPCSI_STATE_INFO_MSG */
/* active AvD timer events processing */
avd_tmr_snd_hb_evh, /* AVD_EVT_TMR_SND_HB */
qsd_ignore_evh, /* AVD_EVT_TMR_CL_INIT */
avd_sidep_tol_tmr_evh, /* AVD_EVT_TMR_SI_DEP_TOL */
+ qsd_ignore_evh, /* AVD_EVT_TMR_ALL_NODE_UP */
/* active AvD MDS events processing */
avd_mds_avd_up_evh, /* AVD_EVT_MDS_AVD_UP */
@@ -532,6 +542,9 @@ static uint32_t initialize(void)
cb->heartbeat_tmr.is_active = false;
cb->heartbeat_tmr.type = AVD_TMR_SND_HB;
cb->heartbeat_tmr_period = AVSV_DEF_HB_PERIOD;
+ cb->all_nodes_synced = false;
+ cb->node_sync_window_closed = false;
+ cb->scs_absence_max_duration = 0;
if ((val = getenv("AVSV_HB_PERIOD")) != nullptr) {
cb->heartbeat_tmr_period = strtoll(val, nullptr, 0);
@@ -598,6 +611,13 @@ static uint32_t initialize(void)
LOG_ER("avd_active_role_initialization FAILED");
goto done;
}
+
+ /* in a normal cluster start there will be no assignments
object found so
+ * nothing happens. Used to cleanup cached RTAs after SCs
recover after
+ * being headless.
+ */
+ avd_susi_cleanup();
+ avd_compcsi_cleanup();
}
else {
rc = avd_standby_role_initialization(cb);
@@ -780,6 +800,8 @@ static void main_loop(void)
**************************************************************************/
static void process_event(AVD_CL_CB *cb_now, AVD_EVT *evt)
{
+ TRACE_ENTER2("evt->rcv_evt %u", evt->rcv_evt);
+
/* check the HA state */
if (cb_now->avail_state_avd == SA_AMF_HA_ACTIVE) {
/* if active call g_avd_actv_list functions */
@@ -824,6 +846,8 @@ static void process_event(AVD_CL_CB *cb_
cb_now->sync_required = true;
delete evt;
+
+ TRACE_LEAVE();
}
/**
diff --git a/osaf/services/saf/amf/amfd/mds.cc
b/osaf/services/saf/amf/amfd/mds.cc
--- a/osaf/services/saf/amf/amfd/mds.cc
+++ b/osaf/services/saf/amf/amfd/mds.cc
@@ -45,13 +45,13 @@
const MDS_CLIENT_MSG_FORMAT_VER avd_avnd_msg_fmt_map_table[] = {
AVSV_AVD_AVND_MSG_FMT_VER_1, AVSV_AVD_AVND_MSG_FMT_VER_2,
AVSV_AVD_AVND_MSG_FMT_VER_3, AVSV_AVD_AVND_MSG_FMT_VER_4,
- AVSV_AVD_AVND_MSG_FMT_VER_5
+ AVSV_AVD_AVND_MSG_FMT_VER_5, AVSV_AVD_AVND_MSG_FMT_VER_6
};
const MDS_CLIENT_MSG_FORMAT_VER avd_avd_msg_fmt_map_table[] = {
AVD_AVD_MSG_FMT_VER_1, AVD_AVD_MSG_FMT_VER_2,
AVD_AVD_MSG_FMT_VER_3, AVD_AVD_MSG_FMT_VER_4,
- AVD_AVD_MSG_FMT_VER_5};
+ AVD_AVD_MSG_FMT_VER_5, AVD_AVD_MSG_FMT_VER_6};
/* fwd decl */
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
@@ -33,11 +33,221 @@
AmfDb<uint32_t, AVD_FAIL_OVER_NODE> *node_list_db = 0; /* SaClmNodeIdT
index */
/*****************************************************************************
- * Function: avd_node_up_func
+ * Function: avd_process_state_info_queue
+ *
+ * Purpose: This function will pull out the queue event and looking for sync
+ * info (sisu, compcsi) event to recover the SI/CSI assignment
+ *
+ * Input: cb - the AVD control block
+ *
+ * Returns: None.
+ *
+ * NOTES:
+ *
+ *
+ **************************************************************************/
+void avd_process_state_info_queue(AVD_CL_CB *cb)
+{
+ uint32_t i;
+ const uint64_t queue_size = cb->evt_queue.size();
+ AVD_EVT_QUEUE *queue_evt = nullptr;
+
+ TRACE_ENTER();
+
+ TRACE("queue_size before processing: %lu", queue_size);
+
+ // recover assignments from state info
+ for(i=0 ; i<queue_size ; i++) {
+ queue_evt = cb->evt_queue.front();
+ osafassert(queue_evt->evt);
+ cb->evt_queue.pop();
+
+ TRACE("rcv_evt: %u", queue_evt->evt->rcv_evt);
+
+ if (queue_evt->evt->rcv_evt == AVD_EVT_ND_SISU_STATE_INFO_MSG ||
+ queue_evt->evt->rcv_evt ==
AVD_EVT_ND_CSICOMP_STATE_INFO_MSG) {
+
+ AVD_DND_MSG* n2d_msg = queue_evt->evt->info.avnd_msg;
+
+ TRACE("msg_type: %u", n2d_msg->msg_type);
+
+ switch(n2d_msg->msg_type) {
+ case AVSV_N2D_ND_SISU_STATE_INFO_MSG:
+
avd_susi_recreate(&n2d_msg->msg_info.n2d_nd_sisu_state_info);
+ break;
+ case AVSV_N2D_ND_CSICOMP_STATE_INFO_MSG:
+
avd_compcsi_recreate(&n2d_msg->msg_info.n2d_nd_csicomp_state_info);
+ break;
+ default:
+ break;
+ }
+
+ avsv_dnd_msg_free(n2d_msg);
+
+ delete queue_evt->evt;
+ delete queue_evt;
+ } else {
+ cb->evt_queue.push(queue_evt);
+ }
+ }
+
+ // Once active amfd looks up the state info from queue, that means node
sync
+ // finishes. Therefore, if the queue is empty, this active amfd is
coming
+ // from a cluster restart, the alarm state should be reset.
+ // Otherwise, amfd is coming from SC recovery from headless, SI alarm
state
+ // should be re-evalutated and raise the alarm in case it's still
unassigned.
+ if (queue_size == 0) {
+ for (std::map<std::string, AVD_SI*>::const_iterator it =
si_db->begin();
+ it != si_db->end(); it++) {
+ AVD_SI *si = it->second;
+ if (si->alarm_sent == true) {
+ si->update_alarm_state(false, false);
+ }
+ }
+ }
+ else {
+ for (std::map<std::string, AVD_SI*>::const_iterator it =
si_db->begin();
+ it != si_db->end(); it++) {
+ AVD_SI *si = it->second;
+ if (si->alarm_sent == false &&
+ si->saAmfSIAssignmentState ==
SA_AMF_ASSIGNMENT_UNASSIGNED) {
+ si->update_alarm_state(true);
+ }
+ }
+ }
+ TRACE("queue_size after processing: %lu", cb->evt_queue.size());
+ TRACE_LEAVE();
+}
+/*****************************************************************************
+ * Function: avd_count_sync_node_size
+ *
+ * Purpose: Helper function count the maximum number of node in cluster
+ * to be synced from headless
+ *
+ * Input: cb - the AVD control block
+ *
+ * Returns: Number of nd
+ *
+ * NOTES:
+ *
+ **************************************************************************/
+uint32_t avd_count_sync_node_size(AVD_CL_CB *cb)
+{
+ uint32_t twon_ncs_su_count = 0;
+ uint32_t count = 0;
+ TRACE_ENTER();
+
+ for (std::map<std::string, AVD_AVND *>::const_iterator it =
node_name_db->begin();
+ it != node_name_db->end(); it++) {
+ AVD_AVND *avnd = it->second;
+ osafassert(avnd);
+ for (const auto& su :avnd->list_of_ncs_su) {
+ if (su->sg_of_su->sg_redundancy_model ==
SA_AMF_2N_REDUNDANCY_MODEL) {
+ twon_ncs_su_count++;
+ continue;
+ }
+ }
+ }
+ // cluster can have 1 SC or more SCs which hosting 2N Opensaf SU
+ // so twon_ncs_su_count at least is 1
+ osafassert(twon_ncs_su_count > 0);
+
+ if (twon_ncs_su_count == 1) {
+ // 1 SC, the rest of nodes could be in sync from headless
+ count = node_name_db->size() - 1;
+ } else {
+ // >=2 SCs, the rest of nodes could be in sync except
active/standby SC
+ count = node_name_db->size() - 2;
+ }
+
+ TRACE("sync node size:%d", count);
+ TRACE_LEAVE();
+ return count;
+}
+/*****************************************************************************
+ * Function: avd_count_node_up
+ *
+ * Purpose: Helper function count number of nodes that sent node_up msg to
+ * director
+ *
+ * Input: cb - the AVD control block
+ *
+ * Returns: Number of node
+ *
+ * NOTES:
+ *
+ *
+ **************************************************************************/
+uint32_t avd_count_node_up(AVD_CL_CB *cb)
+{
+ uint32_t received_count = 0;
+ AVD_AVND *node = nullptr;
+
+ TRACE_ENTER();
+
+ for (std::map<std::string, AVD_AVND *>::const_iterator it =
node_name_db->begin();
+ it != node_name_db->end(); it++) {
+ node = it->second;
+ if (node->node_up_msg_count > 0
+ && node->node_info.nodeId != cb->node_id_avd
+ && node->node_info.nodeId !=
cb->node_id_avd_other)
+ ++received_count;
+ }
+ TRACE("Number of node director(s) that director received node_up
msg:%u",
+ received_count);
+
+ TRACE_LEAVE();
+ return received_count;
+}
+
+/*****************************************************************************
+ * Function: record_node_up_msg_info
+ *
+ * Purpose: Update the rcv_msg_id and adest which are sent from amfnd
+ *
+ * Input: avnd - ptr to the appropriate amfnd
+ * n2d_msg - node_up msg sent from amfnd
+ *
+ * Returns: None
+ *
+ * NOTES:
+ *
+ *
+ **************************************************************************/
+void record_node_up_msg_info(AVD_AVND *avnd, const AVD_DND_MSG *n2d_msg)
+{
+ osafassert(avnd != nullptr);
+
+ avnd->adest = n2d_msg->msg_info.n2d_node_up.adest_address;
+
+ if (n2d_msg->msg_info.n2d_node_up.msg_id >= avnd->rcv_msg_id) {
+ LOG_NO("Received node_up from %x: msg_id %u",
+ n2d_msg->msg_info.n2d_node_up.node_id,
+ n2d_msg->msg_info.n2d_node_up.msg_id);
+
+ avnd->rcv_msg_id = n2d_msg->msg_info.n2d_node_up.msg_id;
+ } else {
+ // This is expected after recovering from a headless state.
+ // NODE_UPs will not be processed until all PLs are up.
+ // In the mean time, we may get other messages from amfnd
+ // that pushes up rcv_msg_id
+ LOG_NO("NODE UP from %x: msg_id out of order. rcv_msg_id %u,
msg_id %u",
+ n2d_msg->msg_info.n2d_node_up.node_id,
+ avnd->rcv_msg_id,
+ n2d_msg->msg_info.n2d_node_up.msg_id);
+ }
+}
+
+
+
+/*****************************************************************************
+ * Function: avd_node_up_evh
*
* Purpose: This function is the handler for node up event indicating
* the arrival of the node_up message. Based on the state machine either
- * It will ignore the message or send all the reg messages to the node.
+ * It will ignore the message or send all the reg messages to the node
+ * or order the node reboot if the node_up message arrives after the node
+ * sync window has closed.
*
* Input: cb - the AVD control block
* evt - The event information.
@@ -54,8 +264,61 @@ void avd_node_up_evh(AVD_CL_CB *cb, AVD_
AVD_AVND *avnd = nullptr;
AVD_DND_MSG *n2d_msg = evt->info.avnd_msg;
uint32_t rc = NCSCC_RC_SUCCESS;
+ uint32_t sync_nd_size = avd_count_sync_node_size(cb);
+ bool act_nd;
- TRACE_ENTER2("from %x", n2d_msg->msg_info.n2d_node_up.node_id);
+ TRACE_ENTER2("from %x, %s", n2d_msg->msg_info.n2d_node_up.node_id,
+ n2d_msg->msg_info.n2d_node_up.node_name.value);
+
+ act_nd = n2d_msg->msg_info.n2d_node_up.node_id == cb->node_id_avd;
+ if (cb->scs_absence_max_duration > 0 &&
+ cb->all_nodes_synced == false &&
+ cb->node_sync_window_closed == false) {
+ avnd = avd_node_get(&n2d_msg->msg_info.n2d_node_up.node_name);
+ if (avnd == nullptr) {
+ LOG_ER("Invalid node_name. Check node_id");
+
+ // perhaps this is a node_up from an old version of
amfnd without headless support
+ // let's check if the node_id is valid
+ if ((avnd =
avd_node_find_nodeid(n2d_msg->msg_info.n2d_node_up.node_id)) == nullptr) {
+ LOG_ER("invalid node ID (%x)",
n2d_msg->msg_info.n2d_node_up.node_id);
+ goto done;
+ }
+ }
+ uint32_t rc_node_up;
+ avnd->node_up_msg_count++;
+ rc_node_up = avd_count_node_up(cb);
+ if (rc_node_up == sync_nd_size) {
+ if (cb->node_sync_tmr.is_active) {
+ avd_stop_tmr(cb, &cb->node_sync_tmr);
+ TRACE("stop NodeSync timer");
+ }
+ cb->all_nodes_synced = true;
+ LOG_NO("Received node_up_msg from all nodes");
+ } else {
+ if (avnd->node_up_msg_count == 1 &&
+ (act_nd ||
n2d_msg->msg_info.n2d_node_up.leds_set)) {
+
+ // start (or restart) timer if this is the
first message
+ // from amfnd-active-SC or amfnd-green-leds-PL
+ cb->node_sync_tmr.type = AVD_TMR_NODE_SYNC;
+ avd_start_tmr(cb, &(cb->node_sync_tmr),
AVSV_DEF_NODE_SYNC_PERIOD);
+
+ TRACE("Received node_up_msg from node:%s.
Start/Restart "
+ " NodeSync timer waiting for
remaining (%d) node(s)",
+
n2d_msg->msg_info.n2d_node_up.node_name.value,
+ sync_nd_size - rc_node_up);
+ goto done;
+ }
+ if (cb->node_sync_tmr.is_active == true) {
+ if (n2d_msg->msg_info.n2d_node_up.leds_set ==
false) {
+ TRACE("NodeSync timer is active, ignore
this node_up msg (nodeid:%x)",
+
n2d_msg->msg_info.n2d_node_up.node_id);
+ goto done;
+ }
+ }
+ }
+ }
/* Cannot use avd_msg_sanity_chk here since this is a special case */
if ((avnd =
avd_node_find_nodeid(n2d_msg->msg_info.n2d_node_up.node_id)) == nullptr) {
@@ -63,6 +326,9 @@ void avd_node_up_evh(AVD_CL_CB *cb, AVD_
goto done;
}
+ /* Retrieve the information from the message */
+ record_node_up_msg_info(avnd, n2d_msg);
+
/* Check the AvD FSM state process node up only if AvD is in init done
or
* APP init state for all nodes except the primary system controller
* whose node up is accepted in config done state.
@@ -73,16 +339,11 @@ void avd_node_up_evh(AVD_CL_CB *cb, AVD_
goto done;
}
- if (avnd->node_state != AVD_AVND_STATE_ABSENT) {
- LOG_WA("invalid node state %u for node %x",
- avnd->node_state,
n2d_msg->msg_info.n2d_node_up.node_id);
- goto done;
+ if ((n2d_msg->msg_info.n2d_node_up.node_id == cb->node_id_avd) &&
(cb->init_state < AVD_INIT_DONE)) {
+ // node up from local AVND
+ avd_process_state_info_queue(cb);
}
- /* Retrive the information from the message */
- avnd->adest = n2d_msg->msg_info.n2d_node_up.adest_address;
- avnd->rcv_msg_id = n2d_msg->msg_info.n2d_node_up.msg_id;
-
if (avnd->node_info.member != SA_TRUE) {
LOG_WA("Not a Cluster Member dropping the msg");
goto done;
@@ -108,7 +369,9 @@ void avd_node_up_evh(AVD_CL_CB *cb, AVD_
}
/* send the Ack message to the node. */
- if (avd_snd_node_ack_msg(cb, avnd, avnd->rcv_msg_id) !=
NCSCC_RC_SUCCESS) {
+ // note: it's important to ack the msg_id received in n2d_msg, rather
than avnd->rcv_msg_id.
+ // They will not always be same when headless option is enabled.
+ if (avd_snd_node_ack_msg(cb, avnd,
n2d_msg->msg_info.n2d_node_up.msg_id) != NCSCC_RC_SUCCESS) {
/* log error that the director is not able to send the message
*/
LOG_ER("%s:%u: %u", __FILE__, __LINE__, avnd->node_info.nodeId);
@@ -119,6 +382,39 @@ void avd_node_up_evh(AVD_CL_CB *cb, AVD_
goto done;
}
+ if (n2d_msg->msg_info.n2d_node_up.leds_set == true) {
+ TRACE("node %x is already up", avnd->node_info.nodeId);
+
+ if (cb->node_sync_window_closed == true &&
avnd->node_up_msg_count == 0) {
+ LOG_WA("Received new node_up_msg from node:%s after
node sync window, "
+ "sending node reboot order to target node",
+ n2d_msg->msg_info.n2d_node_up.node_name.value);
+ avd_d2n_reboot_snd(avnd);
+ goto done;
+ } else if (avnd->reboot) {
+ // delayed node failfast
+ avd_d2n_reboot_snd(avnd);
+ avnd->reboot = false;
+ goto done;
+ }
+ else {
+ // this node is already up
+ avd_node_state_set(avnd, AVD_AVND_STATE_PRESENT);
+ avd_node_oper_state_set(avnd,
SA_AMF_OPERATIONAL_ENABLED);
+
+ // Update readiness state of all SUs which are waiting
for node
+ // oper state
+ for (const auto& su :avnd->list_of_ncs_su) {
+
su->set_readiness_state(SA_AMF_READINESS_IN_SERVICE);
+ }
+ for (const auto& su :avnd->list_of_su) {
+ if (su->is_in_service())
+
su->set_readiness_state(SA_AMF_READINESS_IN_SERVICE);
+ }
+ goto node_joined;
+ }
+ }
+
/* Send role change to this controller AvND */
if (avnd->node_info.nodeId == cb->node_id_avd) {
/* Here obviously the role will be ACT. */
@@ -153,10 +449,11 @@ void avd_node_up_evh(AVD_CL_CB *cb, AVD_
goto done;
}
+ avd_node_state_set(avnd, AVD_AVND_STATE_NO_CONFIG);
+
+node_joined:
LOG_NO("Node '%s' joined the cluster", avnd->node_name);
- avd_node_state_set(avnd, AVD_AVND_STATE_NO_CONFIG);
-
/* checkpoint the node. */
m_AVSV_SEND_CKPT_UPDT_ASYNC_UPDT(cb, avnd, AVSV_CKPT_AVD_NODE_CONFIG);
diff --git a/osaf/services/saf/amf/amfd/ndmsg.cc
b/osaf/services/saf/amf/amfd/ndmsg.cc
--- a/osaf/services/saf/amf/amfd/ndmsg.cc
+++ b/osaf/services/saf/amf/amfd/ndmsg.cc
@@ -357,7 +357,23 @@ uint32_t avd_n2d_msg_rcv(AVD_DND_MSG *rc
cb->peer_msg_fmt_ver = msg_fmt_ver;
}
- evt->rcv_evt = static_cast<AVD_EVT_TYPE>((rcv_msg->msg_type -
AVSV_N2D_NODE_UP_MSG) + AVD_EVT_NODE_UP_MSG);
+ switch (rcv_msg->msg_type) {
+ case AVSV_N2D_ND_SISU_STATE_INFO_MSG:
+ // 'offset lookup' can't be used for this
+ evt->rcv_evt = AVD_EVT_ND_SISU_STATE_INFO_MSG;
+ break;
+ case AVSV_N2D_ND_CSICOMP_STATE_INFO_MSG:
+ // 'offset lookup' can't be used for this
+ evt->rcv_evt = AVD_EVT_ND_CSICOMP_STATE_INFO_MSG;
+ break;
+ default:
+ evt->rcv_evt =
static_cast<AVD_EVT_TYPE>((rcv_msg->msg_type - AVSV_N2D_NODE_UP_MSG) +
AVD_EVT_NODE_UP_MSG);
+ break;
+ }
+
+ osafassert((AVD_EVT_INVALID < evt->rcv_evt)
+ && (evt->rcv_evt < AVD_EVT_MAX));
+
evt->info.avnd_msg = rcv_msg;
if (m_NCS_IPC_SEND(&cb->avd_mbx, evt, NCS_IPC_PRIORITY_HIGH) !=
NCSCC_RC_SUCCESS) {
diff --git a/osaf/services/saf/amf/amfd/ndproc.cc
b/osaf/services/saf/amf/amfd/ndproc.cc
--- a/osaf/services/saf/amf/amfd/ndproc.cc
+++ b/osaf/services/saf/amf/amfd/ndproc.cc
@@ -68,8 +68,9 @@ AVD_AVND *avd_msg_sanity_chk(AVD_EVT* ev
}
if ((node->rcv_msg_id + 1) != msg_id) {
- LOG_WA("%s: invalid msg id %u, from %x should be %u",
- __FUNCTION__, msg_id, node_id, node->rcv_msg_id + 1);
+ LOG_WA("%s: invalid msg id %u, msg type %u, from %x should be
%u",
+ __FUNCTION__, msg_id, evt->info.avnd_msg->msg_type,
+ node_id, node->rcv_msg_id + 1);
return nullptr;
}
@@ -278,6 +279,94 @@ void avd_oper_req_evh(AVD_CL_CB *cb, AVD
TRACE_LEAVE();
}
+/*****************************************************************************
+ * Function: avd_nd_sisu_state_info_evh
+ *
+ * Purpose: This function is the handler for the sync sisu_state_info event.
+ * No process on the event, push in queue or ignore it if the node sync window
+ * has closed.
+ *
+ * Input: cb - the AVD control block
+ * evt - The event information.
+ *
+ * Returns: None.
+ *
+ * NOTES:
+ *
+ *
+ **************************************************************************/
+
+void avd_nd_sisu_state_info_evh(AVD_CL_CB *cb, AVD_EVT *evt)
+{
+ AVD_DND_MSG *n2d_msg = evt->info.avnd_msg;
+ AVD_EVT_QUEUE* state_info_evt;
+
+ TRACE_ENTER();
+ LOG_NO("Receive message with event type:%u, msg_type:%u, from node:%x,
msg_id:%u",
+ evt->rcv_evt,
+ evt->info.avnd_msg->msg_type,
+
evt->info.avnd_msg->msg_info.n2d_nd_sisu_state_info.node_id,
+
evt->info.avnd_msg->msg_info.n2d_nd_sisu_state_info.msg_id);
+
+ if (cb->node_sync_window_closed == false) {
+ state_info_evt = new AVD_EVT_QUEUE();
+ state_info_evt->evt = new AVD_EVT();
+ memcpy(state_info_evt->evt, evt, sizeof(AVD_EVT));
+ state_info_evt->evt->info.avnd_msg = n2d_msg;
+ cb->evt_queue.push(state_info_evt);
+ }
+ else {
+ LOG_WA("Ignore this sisu_state_info message since node sync
window has closed");
+ avsv_dnd_msg_free(n2d_msg);
+ }
+
+ TRACE_LEAVE();
+}
+
+/*****************************************************************************
+ * Function: avd_nd_compcsi_state_info_evh
+ *
+ * Purpose: This function is the handler for the sync compcsi_state_info
event.
+ * No process on the event, push in queue or ignore it if the node sync window
+ * has closed.
+ *
+ * Input: cb - the AVD control block
+ * evt - The event information.
+ *
+ * Returns: None.
+ *
+ * NOTES:
+ *
+ *
+ **************************************************************************/
+
+void avd_nd_compcsi_state_info_evh(AVD_CL_CB *cb, AVD_EVT *evt)
+{
+ AVD_DND_MSG *n2d_msg = evt->info.avnd_msg;
+ AVD_EVT_QUEUE* state_info_evt;
+
+ TRACE_ENTER();
+ LOG_NO("Receive message with event type:%u, msg_type:%u, from node:%x,
msg_id:%u",
+ evt->rcv_evt,
+ evt->info.avnd_msg->msg_type,
+
evt->info.avnd_msg->msg_info.n2d_nd_csicomp_state_info.node_id,
+
evt->info.avnd_msg->msg_info.n2d_nd_csicomp_state_info.msg_id);
+
+ if (cb->node_sync_window_closed == false) {
+ state_info_evt = new AVD_EVT_QUEUE();
+ state_info_evt->evt = new AVD_EVT();
+ memcpy(state_info_evt->evt, evt, sizeof(AVD_EVT));
+ state_info_evt->evt->info.avnd_msg = n2d_msg;
+ cb->evt_queue.push(state_info_evt);
+ }
+ else {
+ LOG_WA("Ignore this compcsi_state_info message since node sync
window has closed");
+ avsv_dnd_msg_free(n2d_msg);
+ }
+
+ TRACE_LEAVE();
+}
+
/**
* handler to report error response to imm for any pending admin operation on
comp
*
@@ -721,7 +810,10 @@ void avd_data_update_req_evh(AVD_CL_CB *
}
if ((node->node_state == AVD_AVND_STATE_ABSENT) || (node->node_state ==
AVD_AVND_STATE_GO_DOWN)) {
- LOG_ER("%s: invalid node state %u", __FUNCTION__,
node->node_state);
+ LOG_ER("%s: node %x, receive msg_id(%u) in invalid node state
%u",
+ __FUNCTION__, node->node_info.nodeId,
+ n2d_msg->msg_info.n2d_data_req.msg_id,
node->node_state);
+
goto done;
}
@@ -883,6 +975,11 @@ void avd_data_update_req_evh(AVD_CL_CB *
l_val = ntohl(*((uint32_t
*)&n2d_msg->msg_info.n2d_data_req.param_info.value[0]));
su->set_oper_state(l_val);
}
+
+ if (su->is_in_service() == true) {
+
su->set_readiness_state(SA_AMF_READINESS_IN_SERVICE);
+ }
+
break;
case saAmfSUPresenceState_ID:
TRACE("su pres state");
diff --git a/osaf/services/saf/amf/amfd/node.cc
b/osaf/services/saf/amf/amfd/node.cc
--- a/osaf/services/saf/amf/amfd/node.cc
+++ b/osaf/services/saf/amf/amfd/node.cc
@@ -57,6 +57,7 @@ uint32_t avd_node_add_nodeid(AVD_AVND *n
if ((node_id_db->find(node->node_info.nodeId) == nullptr) &&
(node->node_info.nodeId != 0)) {
+ TRACE("added node %d", node->node_info.nodeId);
rc = node_id_db->insert(node->node_info.nodeId, node);
osafassert(rc == NCSCC_RC_SUCCESS);
}
@@ -164,6 +165,8 @@ AVD_AVND *avd_node_new(const SaNameT *dn
AVD_AVND *node;
node = new AVD_AVND(dn);
+ node->node_up_msg_count = 0;
+ node->reboot = false;
return node;
}
@@ -409,8 +412,10 @@ void avd_node_state_set(AVD_AVND *node,
osafassert(node_state <= AVD_AVND_STATE_NCS_INIT);
TRACE_ENTER2("'%s' %s => %s", node->name.value,
node_state_name[node->node_state],
node_state_name[node_state]);
- node->node_state = node_state;
- m_AVSV_SEND_CKPT_UPDT_ASYNC_UPDT(avd_cb, node,
AVSV_CKPT_AVND_NODE_STATE);
+ if (node->node_state != node_state) {
+ node->node_state = node_state;
+ m_AVSV_SEND_CKPT_UPDT_ASYNC_UPDT(avd_cb, node,
AVSV_CKPT_AVND_NODE_STATE);
+ }
TRACE_LEAVE();
}
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
@@ -1982,6 +1982,63 @@ done:
return rc;
}
+/**
+ * @Brief Check if SI Dependency relations between SIs are still valid
+ * as cluster has just being came from headless. The dependent SIs
+ * which have any unassigned sponsor SI will remove the assignments.
+ *
+ * @param None
+ * @Return None
+*/
+void adjust_delayed_sidep(void)
+{
+ AVD_SU_SI_REL *curr_susi;
+ bool rescan = true;
+ TRACE_ENTER();
+
+ // Searching for the dependent SIs which's sponsored SI(s)
+ // had removed assignment in headless.
+ while (rescan) {
+ rescan = false;
+ for (std::map<std::string, AVD_SG*>::const_iterator it =
sg_db->begin();
+ it != sg_db->end(); it++) {
+ AVD_SG *i_sg = it->second;
+ if (i_sg->list_of_su.empty() || (i_sg->sg_ncs_spec ==
true)) {
+ continue;
+ }
+ for (const auto& si : i_sg->list_of_si) {
+ if (si->list_of_sisu &&
+ si->saAmfSIAssignmentState !=
SA_AMF_ASSIGNMENT_UNASSIGNED) {
+ bool any_unassign_spsi = false;
+ AVD_SPONS_SI_NODE *spsi_node =
si->spons_si_list;
+ for(; spsi_node != nullptr &&
!any_unassign_spsi;
+ spsi_node =
spsi_node->next) {
+ // if any of sponsored si has
no assignment
+ // @si will remove its all
assignments
+ if
((spsi_node->si->curr_standby_assignments() +
+
spsi_node->si->curr_active_assignments()) == 0) {
+ // remove all sisu of
@si
+ for(curr_susi =
si->list_of_sisu; curr_susi;
+
curr_susi = curr_susi->si_next) {
+ if
(curr_susi->fsm == AVD_SU_SI_STATE_ASGND) {
+
LOG_NO("Remove '%s' from '%s' due to sponsor SI %s is unassigned",
+
curr_susi->si->name.value, curr_susi->su->name.value,
+
spsi_node->si->name.value);
+
avd_susi_del_send(curr_susi);
+
any_unassign_spsi = true;
+ // Need
to rescan due to recursive dependencies
+ rescan
= true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ TRACE_LEAVE();
+}
AVD_SU* AVD_SG::first_su()
{
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
@@ -3534,6 +3534,146 @@ done:
TRACE_LEAVE();
}
+void SG_2N::adjust_delayed_failover(AVD_CL_CB *cb) {
+ AVD_SU_SI_REL *curr_susi;
+ TRACE_ENTER();
+
+ // Check AdminState of node/sg/su whether is LOCKED or SHUTTING_DOWN
+ // which states will cause removal of assignment
+ for (const auto& su : list_of_su) {
+ SaAmfHAStateT su_ha_state;
+ TRACE("Check AdminState of SU/SG/Node, SU:'%s',
saAmfSUAdminState:%u, "
+ "saAmfSGAdminState:%u, saAmfNodeAdminState:%u, "
+ "saAmfSUNumCurrActiveSIs:%u,
saAmfSUNumCurrStandbySIs:%u",
+ su->name.value,
+ su->saAmfSUAdminState,
+ su->sg_of_su->saAmfSGAdminState,
+ su->su_on_node->saAmfNodeAdminState,
+ su->saAmfSUNumCurrActiveSIs,
+ su->saAmfSUNumCurrStandbySIs);
+
+ if (su->saAmfSUAdminState == SA_AMF_ADMIN_LOCKED ||
+ su->sg_of_su->saAmfSGAdminState == SA_AMF_ADMIN_LOCKED
||
+ su->su_on_node->saAmfNodeAdminState ==
SA_AMF_ADMIN_LOCKED ||
+ su->saAmfSUAdminState == SA_AMF_ADMIN_SHUTTING_DOWN ||
+ su->sg_of_su->saAmfSGAdminState ==
SA_AMF_ADMIN_SHUTTING_DOWN ||
+ su->su_on_node->saAmfNodeAdminState ==
SA_AMF_ADMIN_SHUTTING_DOWN) {
+
+ if (su->list_of_susi) {
+ su_ha_state = avd_su_state_determine(su);
+ if (su_ha_state == SA_AMF_HA_QUIESCED ||
+ su_ha_state == SA_AMF_HA_STANDBY ||
+ su_ha_state == SA_AMF_HA_QUIESCING) {
+ // remove all susi belong to this su
+ avd_sg_su_si_del_snd(cb, su);
+ } else if (su_ha_state == SA_AMF_HA_ACTIVE) {
+ // quiesced this su
+ avd_sg_su_si_mod_snd(cb, su,
SA_AMF_HA_QUIESCED);
+ }
+ avd_sg_su_oper_list_add(cb, su, false);
+ set_fsm_state(AVD_SG_FSM_SG_REALIGN);
+ }
+ // directly move from SHUTTING_DOWN to LOCKED
+ if (su->saAmfSUAdminState == SA_AMF_ADMIN_SHUTTING_DOWN)
+ su->set_admin_state(SA_AMF_ADMIN_LOCKED);
+ if (su->sg_of_su->saAmfSGAdminState ==
SA_AMF_ADMIN_SHUTTING_DOWN)
+ avd_sg_admin_state_set(su->sg_of_su,
SA_AMF_ADMIN_LOCKED);
+ if (su->su_on_node->saAmfNodeAdminState ==
SA_AMF_ADMIN_SHUTTING_DOWN)
+ node_admin_state_set(su->su_on_node,
SA_AMF_ADMIN_LOCKED);
+ }
+ }
+
+ // Check AdminState of si whether is LOCKED or SHUTTING_DOWN
+ for (const auto& si : list_of_si) {
+
+ AVD_SU_SI_REL *curr_active_susi = nullptr;
+ AVD_SU_SI_REL *curr_quiesce_susi = nullptr;
+ AVD_SU_SI_REL *curr_standby_susi = nullptr;
+
+ TRACE("Check SI:'%s', saAmfSIAdminState:%u,
saAmfSINumCurrActiveAssignments:%u, "
+ "saAmfSINumCurrStandbyAssignments:%u",
+ si->name.value,
+ si->saAmfSIAdminState,
+ si->saAmfSINumCurrActiveAssignments,
+ si->saAmfSINumCurrStandbyAssignments);
+
+ for (curr_susi = si->list_of_sisu; curr_susi;
+ curr_susi = curr_susi->si_next) {
+
+ TRACE("Check SUSI:'%s,%s', HaState:%u",
curr_susi->su->name.value,
+ curr_susi->si->name.value,
+ curr_susi->state);
+
+ if (si->saAmfSIAdminState == SA_AMF_ADMIN_SHUTTING_DOWN
||
+ si->saAmfSIAdminState == SA_AMF_ADMIN_LOCKED) {
+ // only process assigned susi, ignore the
others due to
+ // being modified or unassigned, ...
+ if (curr_susi->fsm == AVD_SU_SI_STATE_ASGND) {
+ if (curr_susi->state ==
SA_AMF_HA_STANDBY ||
+ curr_susi->state ==
SA_AMF_HA_QUIESCED ||
+ curr_susi->state ==
SA_AMF_HA_QUIESCING) {
+ // remove one susi
+ avd_susi_del_send(curr_susi);
+ } else if (curr_susi->state ==
SA_AMF_HA_ACTIVE) {
+ // quiesced one susi
+ avd_susi_mod_send(curr_susi,
SA_AMF_HA_QUIESCED);
+ }
+ set_fsm_state(AVD_SG_FSM_SG_REALIGN);
+ avd_sg_su_oper_list_add(cb,
curr_susi->su, false);
+ }
+ // directly move from SHUTTING_DOWN to LOCKED
+ if (si->saAmfSIAdminState ==
SA_AMF_ADMIN_SHUTTING_DOWN)
+
si->set_admin_state(SA_AMF_ADMIN_LOCKED);
+ }
+ if (curr_susi->fsm != AVD_SU_SI_STATE_ASGND)
+ continue;
+
+ if (curr_susi->state == SA_AMF_HA_ACTIVE)
+ curr_active_susi = curr_susi;
+ else if (curr_susi->state == SA_AMF_HA_STANDBY)
+ curr_standby_susi = curr_susi;
+ else
+ curr_quiesce_susi = curr_susi;
+ }
+
+ if (!curr_active_susi && !curr_quiesce_susi &&
!curr_standby_susi)
+ continue;
+
+ // at this point in time, there could be inappropriate susi in
term of
+ // HA state due to uncompleted failover/si-swap around the time
cluster
+ // was going into headless.
+ // Adjust the HA state if neccessary.
+ if (curr_active_susi) {
+ if (!curr_standby_susi && curr_quiesce_susi) {
+ avd_sg_su_si_mod_snd(cb, curr_quiesce_susi->su,
SA_AMF_HA_STANDBY);
+ avd_sg_su_oper_list_add(cb,
curr_quiesce_susi->su, false);
+ set_fsm_state(AVD_SG_FSM_SG_REALIGN);
+ }
+ } else {
+ if (curr_standby_susi && curr_quiesce_susi) {
+ avd_sg_su_si_mod_snd(cb, curr_quiesce_susi->su,
SA_AMF_HA_STANDBY);
+ avd_sg_su_oper_list_add(cb,
curr_quiesce_susi->su, false);
+
+ avd_sg_su_si_mod_snd(cb, curr_standby_susi->su,
SA_AMF_HA_ACTIVE);
+ avd_sg_su_oper_list_add(cb,
curr_standby_susi->su, false);
+
+ set_fsm_state(AVD_SG_FSM_SG_REALIGN);
+ } else if (!curr_standby_susi && curr_quiesce_susi) {
+ avd_sg_su_si_mod_snd(cb, curr_quiesce_susi->su,
SA_AMF_HA_ACTIVE);
+ avd_sg_su_oper_list_add(cb,
curr_quiesce_susi->su, false);
+
+ set_fsm_state(AVD_SG_FSM_SG_REALIGN);
+ } else if (curr_standby_susi && !curr_quiesce_susi) {
+ avd_sg_su_si_mod_snd(cb, curr_standby_susi->su,
SA_AMF_HA_ACTIVE);
+ avd_sg_su_oper_list_add(cb,
curr_standby_susi->su, false);
+
+ set_fsm_state(AVD_SG_FSM_SG_REALIGN);
+ }
+ }
+ }
+ TRACE_LEAVE();
+}
+
uint32_t SG_2N::su_admin_down(AVD_CL_CB *cb, AVD_SU *su, AVD_AVND *avnd) {
uint32_t rc = NCSCC_RC_FAILURE;
diff --git a/osaf/services/saf/amf/amfd/sg_nored_fsm.cc
b/osaf/services/saf/amf/amfd/sg_nored_fsm.cc
--- a/osaf/services/saf/amf/amfd/sg_nored_fsm.cc
+++ b/osaf/services/saf/amf/amfd/sg_nored_fsm.cc
@@ -949,6 +949,12 @@ void SG_NORED::node_fail(AVD_CL_CB *cb,
TRACE_LEAVE();
}
+void SG_NORED::adjust_delayed_failover(AVD_CL_CB *cb) {
+ TRACE_ENTER();
+ TRACE("Currently not applicable");
+ TRACE_LEAVE();
+}
+
uint32_t SG_NORED::su_admin_down(AVD_CL_CB *cb, AVD_SU *su, AVD_AVND *avnd) {
TRACE_ENTER2("%u", su->sg_of_su->sg_fsm_state);
diff --git a/osaf/services/saf/amf/amfd/sg_npm_fsm.cc
b/osaf/services/saf/amf/amfd/sg_npm_fsm.cc
--- a/osaf/services/saf/amf/amfd/sg_npm_fsm.cc
+++ b/osaf/services/saf/amf/amfd/sg_npm_fsm.cc
@@ -4200,6 +4200,30 @@ void SG_NPM::node_fail(AVD_CL_CB *cb, AV
return;
}
+void SG_NPM::adjust_delayed_failover(AVD_CL_CB *cb) {
+ uint32_t stb_si_count = 0;
+ uint32_t act_si_count = 0;
+ TRACE_ENTER();
+
+ for (const auto& su : list_of_su) {
+ stb_si_count += su->saAmfSUNumCurrStandbySIs;
+ act_si_count += su->saAmfSUNumCurrActiveSIs;
+ }
+
+ if (stb_si_count > 0 && act_si_count == 0) {
+ // TODO: smoothly transfer the assignment from STANDBY to ACTIVE
+ // as well as satisfying the configurations by:
+ // saAmfSGNumPrefAssignedSUs, saAmfSGMaxActiveSIsperSU,
+ // saAmfSGNumPrefActiveSUs, saAmfSIPrefActiveAssignments
+ for (const auto& si : list_of_si) {
+ si->delete_assignments(cb);
+ }
+ set_fsm_state(AVD_SG_FSM_SG_REALIGN);
+ }
+
+ TRACE_LEAVE();
+}
+
uint32_t SG_NPM::su_admin_down(AVD_CL_CB *cb, AVD_SU *su, AVD_AVND *avnd) {
uint32_t rc;
diff --git a/osaf/services/saf/amf/amfd/sg_nway_fsm.cc
b/osaf/services/saf/amf/amfd/sg_nway_fsm.cc
--- a/osaf/services/saf/amf/amfd/sg_nway_fsm.cc
+++ b/osaf/services/saf/amf/amfd/sg_nway_fsm.cc
@@ -521,6 +521,30 @@ done:
TRACE_LEAVE();
}
+void SG_NWAY::adjust_delayed_failover(AVD_CL_CB *cb) {
+ uint32_t stb_si_count = 0;
+ uint32_t act_si_count = 0;
+ TRACE_ENTER();
+
+ for (const auto& su : list_of_su) {
+ stb_si_count += su->saAmfSUNumCurrStandbySIs;
+ act_si_count += su->saAmfSUNumCurrActiveSIs;
+ }
+
+ if (stb_si_count > 0 && act_si_count == 0) {
+ // TODO: smoothly transfer the assignment from STANDBY to ACTIVE
+ // as well as satisfying the configurations by:
+ // saAmfSGNumPrefAssignedSUs, saAmfSGMaxActiveSIsperSU,
+ // saAmfSGNumPrefActiveSUs, saAmfSIPrefActiveAssignments
+ for (const auto& si : list_of_si) {
+ si->delete_assignments(cb);
+ }
+ set_fsm_state(AVD_SG_FSM_SG_REALIGN);
+ }
+
+ TRACE_LEAVE();
+}
+
uint32_t SG_NWAY::su_admin_down(AVD_CL_CB *cb, AVD_SU *su, AVD_AVND *avnd) {
AVD_SU_SI_REL *curr_susi = 0;
SaAmfHAStateT state;
diff --git a/osaf/services/saf/amf/amfd/sg_nwayact_fsm.cc
b/osaf/services/saf/amf/amfd/sg_nwayact_fsm.cc
--- a/osaf/services/saf/amf/amfd/sg_nwayact_fsm.cc
+++ b/osaf/services/saf/amf/amfd/sg_nwayact_fsm.cc
@@ -1507,6 +1507,12 @@ void SG_NACV::node_fail(AVD_CL_CB *cb, A
return;
}
+void SG_NACV::adjust_delayed_failover(AVD_CL_CB *cb) {
+ TRACE_ENTER();
+ TRACE("Currently not applicable");
+ TRACE_LEAVE();
+}
+
uint32_t SG_NACV::su_admin_down(AVD_CL_CB *cb, AVD_SU *su, AVD_AVND *avnd) {
TRACE_ENTER2("%u", su->sg_of_su->sg_fsm_state);
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
@@ -278,7 +278,7 @@ done:
* @param[in] su
*
**/
-static void su_try_repair(const AVD_SU *su)
+void su_try_repair(const AVD_SU *su)
{
TRACE_ENTER2("Repair for SU:'%s'", su->name.value);
@@ -287,12 +287,12 @@ static void su_try_repair(const AVD_SU *
(su->saAmfSUPresenceState !=
SA_AMF_PRESENCE_INSTANTIATION_FAILED) &&
(su->saAmfSUPresenceState !=
SA_AMF_PRESENCE_TERMINATION_FAILED)) {
- saflog(LOG_NOTICE, amfSvcUsrName, "Ordering Auto repair of '%s'
as sufailover repair action",
- su->sg_of_su->name.value);
+ LOG_NO("Ordering Auto repair of '%s' as sufailover repair
action",
+ su->name.value);
avd_admin_op_msg_snd(&su->name, AVSV_SA_AMF_SU,
static_cast<SaAmfAdminOperationIdT>(SA_AMF_ADMIN_REPAIRED), su->su_on_node);
} else {
- saflog(LOG_NOTICE, amfSvcUsrName, "Autorepair not done for
'%s'", su->sg_of_su->name.value);
+ LOG_NO("Autorepair not done for '%s'", su->name.value);
}
TRACE_LEAVE();
@@ -480,8 +480,11 @@ static uint32_t sg_su_failover_func(AVD_
}
}
+ TRACE("init_state %u", avd_cb->init_state);
+
/*If the AvD is in AVD_APP_STATE then reassign all the SUSI assignments
for this SU */
- if (avd_cb->init_state == AVD_APP_STATE) {
+ if (avd_cb->init_state == AVD_APP_STATE ||
+ avd_cb->scs_absence_max_duration > 0) {
/* Unlike active, quiesced and standby HA states, assignment
counters
in quiescing HA state are updated when AMFD receives
assignment
response from AMFND. During sufailover amfd will not receive
@@ -489,6 +492,9 @@ static uint32_t sg_su_failover_func(AVD_
So if any SU is under going modify operation then update
assignment
counters for those SUSIs which are in quiescing state in the
SU.
*/
+ TRACE("Reassign SUSI assignments for %s, init_state %u",
+ su->name.value, avd_cb->init_state);
+
for (AVD_SU_SI_REL *susi = su->list_of_susi; susi; susi =
susi->su_next) {
if ((susi->fsm == AVD_SU_SI_STATE_MODIFY) &&
(susi->state == SA_AMF_HA_QUIESCING)) {
@@ -738,7 +744,9 @@ void avd_su_oper_state_evh(AVD_CL_CB *cb
* disabled.
*/
- if (cb->init_state == AVD_INIT_DONE) {
+ TRACE("init_state %u", cb->init_state);
+
+ if (cb->init_state == AVD_INIT_DONE &&
cb->scs_absence_max_duration == 0) {
su->set_oper_state(SA_AMF_OPERATIONAL_DISABLED);
su->set_readiness_state(SA_AMF_READINESS_OUT_OF_SERVICE);
if (n2d_msg->msg_info.n2d_opr_state.node_oper_state ==
SA_AMF_OPERATIONAL_DISABLED) {
@@ -752,7 +760,11 @@ void avd_su_oper_state_evh(AVD_CL_CB *cb
}
} /* if
(n2d_msg->msg_info.n2d_opr_state.node_oper_state ==
SA_AMF_OPERATIONAL_DISABLED) */
} /* if(cb->init_state == AVD_INIT_DONE) */
- else if (cb->init_state == AVD_APP_STATE) {
+ else if (cb->init_state == AVD_APP_STATE ||
+ (cb->init_state == AVD_INIT_DONE &&
cb->scs_absence_max_duration > 0)) {
+
+ TRACE("Setting SU to disabled in init_state %u",
cb->init_state);
+
su->set_oper_state(SA_AMF_OPERATIONAL_DISABLED);
su->set_readiness_state(SA_AMF_READINESS_OUT_OF_SERVICE);
if (n2d_msg->msg_info.n2d_opr_state.node_oper_state ==
SA_AMF_OPERATIONAL_DISABLED) {
@@ -873,6 +885,20 @@ void avd_su_oper_state_evh(AVD_CL_CB *cb
}
}
} else { /* if(su->sg_of_su->sg_ncs_spec == true) */
+ if (avd_cb->scs_absence_max_duration > 0 &&
+ su->saAmfSUPresenceState ==
SA_AMF_PRESENCE_UNINSTANTIATED &&
+ su->saAmfSUPreInstantiable == false) {
+ // this is to allow non NPI SUs to be repaired
if
+ // headless mode is enabled. Otherwise, the code
+ // following will assume the SU is already in
service
+ // when it failed to instantiate while headless
+
+ if (cb->init_state == AVD_APP_STATE) {
+ LOG_NO("Setting NPI SU '%s' to OOS
after headless state", su->name.value);
+
su->set_readiness_state(SA_AMF_READINESS_OUT_OF_SERVICE);
+ }
+ }
+
/* If oper state of Uninstantiated SU got ENABLED so
try to instantiate it
after evaluating SG. */
if (su->saAmfSUPresenceState ==
SA_AMF_PRESENCE_UNINSTANTIATED) {
@@ -1726,6 +1752,14 @@ uint32_t avd_sg_app_su_inst_func(AVD_CL_
TRACE_ENTER2("'%s'", sg->name.value);
for (const auto& i_su : sg->list_of_su) {
+ TRACE("Checking '%s'", i_su->name.value);
+
+ TRACE("saAmfSuReadinessState: %u", i_su->saAmfSuReadinessState);
+ TRACE("saAmfSUPreInstantiable: %u",
i_su->saAmfSUPreInstantiable);
+ TRACE("saAmfSUPresenceState: %u", i_su->saAmfSUPresenceState);
+ TRACE("saAmfSUOperState: %u", i_su->saAmfSUOperState);
+ TRACE("term_state: %u", i_su->term_state);
+
su_node_ptr = i_su->get_node_ptr();
num_su++;
/* Check if the SU is inservice */
@@ -1746,6 +1780,7 @@ uint32_t avd_sg_app_su_inst_func(AVD_CL_
(any_ng_in_locked_in_state(su_node_ptr) == false)) {
if (i_su->is_in_service() == true) {
+ TRACE("Calling su_insvc() for '%s'",
i_su->name.value);
i_su->set_readiness_state(SA_AMF_READINESS_IN_SERVICE);
i_su->sg_of_su->su_insvc(cb, i_su);
diff --git a/osaf/services/saf/amf/amfd/si.cc b/osaf/services/saf/amf/amfd/si.cc
--- a/osaf/services/saf/amf/amfd/si.cc
+++ b/osaf/services/saf/amf/amfd/si.cc
@@ -634,6 +634,10 @@ static AVD_SI *si_create(SaNameT *si_nam
si->saAmfSIAdminState = SA_AMF_ADMIN_UNLOCKED;
}
+ if
(immutil_getAttr(const_cast<SaImmAttrNameT>("saAmfUnassignedAlarmStatus"),
attributes, 0, &si->alarm_sent) != SA_AIS_OK) {
+ /* Empty, assign default value */
+ si->alarm_sent = false;
+ }
rc = 0;
done:
@@ -673,6 +677,7 @@ SaAisErrorT avd_si_config_get(AVD_APP *a
const_cast<SaImmAttrNameT>("saAmfSIPrefActiveAssignments"),
const_cast<SaImmAttrNameT>("saAmfSIPrefStandbyAssignments"),
const_cast<SaImmAttrNameT>("saAmfSIAdminState"),
+ const_cast<SaImmAttrNameT>("saAmfUnassignedAlarmStatus"),
nullptr
};
@@ -1293,8 +1298,8 @@ void AVD_SI::update_ass_state()
if (saAmfSINumCurrActiveAssignments == 0) {
newState = SA_AMF_ASSIGNMENT_UNASSIGNED;
} else {
- osafassert(saAmfSINumCurrActiveAssignments == 1);
- osafassert(saAmfSINumCurrStandbyAssignments == 0);
+ //osafassert(saAmfSINumCurrActiveAssignments == 1);
+ //osafassert(saAmfSINumCurrStandbyAssignments == 0);
newState = SA_AMF_ASSIGNMENT_FULLY_ASSIGNED;
}
break;
@@ -1314,21 +1319,14 @@ void AVD_SI::update_ass_state()
/* alarm & notifications */
if (saAmfSIAssignmentState == SA_AMF_ASSIGNMENT_UNASSIGNED) {
- avd_send_si_unassigned_alarm(&name);
- alarm_sent = true;
- m_AVSV_SEND_CKPT_UPDT_ASYNC_UPDT(avd_cb, this,
AVSV_CKPT_SI_ALARM_SENT);
+ update_alarm_state(true);
}
else {
avd_send_si_assigned_ntf(&name, oldState,
saAmfSIAssignmentState);
-
/* Clear of alarm */
if ((oldState == SA_AMF_ASSIGNMENT_UNASSIGNED) &&
alarm_sent) {
- avd_alarm_clear(&name,
SA_AMF_NTFID_SI_UNASSIGNED, SA_NTF_SOFTWARE_ERROR);
- m_AVSV_SEND_CKPT_UPDT_ASYNC_UPDT(avd_cb, this,
AVSV_CKPT_SI_ALARM_SENT);
+ update_alarm_state(false);
}
-
- /* always reset in case the SI has been recycled */
- alarm_sent = false;
}
avd_saImmOiRtObjectUpdate(&name, "saAmfSIAssignmentState",
@@ -1501,3 +1499,28 @@ void AVD_SI::update_sirank(uint32_t newS
saAmfSIRank = (newSiRank == 0) ? ~0U : newSiRank;
sg->add_si(this);
}
+
+/*
+ * @brief Update alarm_sent by new value of @alarm_state,
+ * then update saAmfUnassignedAlarmStatus IMM attribute
+ * and raise/clear SI unassigned alarm (if specified) accordingly
+ * @param [in] @alarm_state: Indication of alarm raising/clearing
+ * @param [in] @sent_notification: Indication of sending alarm
+ * raising/clearing notification
+ */
+void AVD_SI::update_alarm_state(bool alarm_state, bool sent_notification)
+{
+ alarm_sent = alarm_state;
+ avd_saImmOiRtObjectUpdate(&name, "saAmfUnassignedAlarmStatus",
+ SA_IMM_ATTR_SAUINT32T, &alarm_sent);
+ m_AVSV_SEND_CKPT_UPDT_ASYNC_UPDT(avd_cb, this, AVSV_CKPT_SI_ALARM_SENT);
+
+ if (sent_notification == true) {
+ if (alarm_sent == true) {
+ avd_send_si_unassigned_alarm(&name);
+ }
+ else {
+ avd_alarm_clear(&name, SA_AMF_NTFID_SI_UNASSIGNED,
SA_NTF_SOFTWARE_ERROR);
+ }
+ }
+}
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
@@ -775,3 +775,126 @@ done:
TRACE_LEAVE2("quiesc_role:%u",quiesc_role);
return quiesc_role;
}
+
+/**
+ * Clean up SUSI objects by searching for SaAmfSIAssignment instances in IMM
+ * @return SA_AIS_OK when OK
+ */
+SaAisErrorT avd_susi_cleanup(void)
+{
+ SaAisErrorT rc;
+ SaImmSearchHandleT searchHandle;
+ SaImmSearchParametersT_2 searchParam;
+ const char *className = "SaAmfSIAssignment";
+
+ TRACE_ENTER();
+
+ searchParam.searchOneAttr.attrName =
const_cast<SaImmAttrNameT>("SaImmAttrClassName");
+ searchParam.searchOneAttr.attrValueType = SA_IMM_ATTR_SASTRINGT;
+ searchParam.searchOneAttr.attrValue = &className;
+
+ if ((rc = immutil_saImmOmSearchInitialize_2(avd_cb->immOmHandle,
nullptr, SA_IMM_SUBTREE,
+ SA_IMM_SEARCH_ONE_ATTR | SA_IMM_SEARCH_GET_NO_ATTR, &searchParam,
+ nullptr, &searchHandle)) != SA_AIS_OK) {
+ LOG_ER("%s: saImmOmSearchInitialize_2 failed: %u",
__FUNCTION__, rc);
+ goto done;
+ }
+
+ SaNameT siass_name;
+ const SaImmAttrValuesT_2 **attributes;
+ while ((rc = immutil_saImmOmSearchNext_2(searchHandle, &siass_name,
+ (SaImmAttrValuesT_2 ***)&attributes))
== SA_AIS_OK) {
+ avd_saImmOiRtObjectDelete(&siass_name);
+ }
+
+ (void)immutil_saImmOmSearchFinalize(searchHandle);
+
+done:
+ TRACE_LEAVE();
+ return SA_AIS_OK;
+}
+
+/**
+ * Recreates SUSI objects by with information retrieved from node directors.
+ * Update relevant runtime attributes
+ * @return SA_AIS_OK when OK
+ */
+SaAisErrorT avd_susi_recreate(AVSV_N2D_ND_SISU_STATE_MSG_INFO* info)
+{
+ TRACE_ENTER2("msg_id: %u node_id: %u num_sisu: %u", info->msg_id,
+ info->node_id, info->num_sisu);
+ AVD_SU_SI_REL *susi = nullptr;
+ AVD_AVND *node = nullptr;
+
+ const AVSV_SISU_STATE_MSG *susi_state = nullptr;
+ const AVSV_SU_STATE_MSG *su_state = nullptr;
+
+ node = avd_node_find_nodeid(info->node_id);
+ if (node == 0) {
+ LOG_ER("Node %" PRIx32 " has left the cluster", info->node_id);
+ return SA_AIS_ERR_NOT_EXIST;
+ }
+
+ for (su_state = info->su_list; su_state != nullptr;
+ su_state = su_state->next) {
+
+ AVD_SU *su = su_db->find(Amf::to_string(&su_state->safSU));
+ osafassert(su);
+
+ // present state
+
su->set_pres_state(static_cast<SaAmfPresenceStateT>(su_state->su_pres_state));
+
+ // oper state
+ su->set_oper_state(su_state->su_oper_state);
+
+ // . readiness state is updated when node_up of PL is accepted
+ // . saAmfSUPreInstantiable wouldn't change during headless
+ // so they need not to update
+ // . saAmfSUNumCurrActiveSIs & saAmfSUNumCurrStandbySIs to be
updated
+ // during avd_susi_create()
+
+ // restart count
+ su->saAmfSURestartCount = su_state->su_restart_cnt;
+ avd_saImmOiRtObjectUpdate(&su->name,
+
const_cast<SaImmAttrNameT>("saAmfSURestartCount"), SA_IMM_ATTR_SAUINT32T,
+ &su->saAmfSURestartCount);
+ m_AVSV_SEND_CKPT_UPDT_ASYNC_UPDT(avd_cb, su,
AVSV_CKPT_SU_RESTART_COUNT);
+ }
+
+ for (susi_state = info->sisu_list; susi_state != nullptr;
+ susi_state = susi_state->next) {
+
+ assert(susi_state->safSI.length > 0);
+ AVD_SI *si = si_db->find(Amf::to_string(&susi_state->safSI));
+ osafassert(si);
+
+ AVD_SU *su = su_db->find(Amf::to_string(&susi_state->safSU));
+ osafassert(su);
+
+ SaAmfHAStateT ha_state = susi_state->saAmfSISUHAState;
+
+ susi = avd_su_susi_find(avd_cb, su, &susi_state->safSI);
+ if (susi == nullptr) {
+ susi = avd_susi_create(avd_cb, si, su, ha_state, false);
+ osafassert(susi);
+ } else {
+ avd_susi_ha_state_set(susi, ha_state);
+ }
+ susi->fsm = AVD_SU_SI_STATE_ASGND;
+
+ if (susi->state == SA_AMF_HA_QUIESCING) {
+ susi->su->inc_curr_act_si();
+ susi->si->inc_curr_act_ass();
+ }
+ // TODO: check if su needs saAmfSUHostedByNode update
+ su->saAmfSUHostedByNode = node->name;
+ avd_saImmOiRtObjectUpdate(&su->name, "saAmfSUHostedByNode",
+ SA_IMM_ATTR_SANAMET, &su->saAmfSUHostedByNode);
+
+ m_AVSV_SEND_CKPT_UPDT_ASYNC_ADD(avd_cb, susi,
AVSV_CKPT_AVD_SI_ASS);
+ }
+
+
+ TRACE_LEAVE();
+ return SA_AIS_OK;
+}
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
@@ -1368,21 +1368,14 @@ static SaAisErrorT su_ccb_completed_modi
SaAisErrorT rc = SA_AIS_OK;
const SaImmAttrModificationT_2 *attr_mod;
int i = 0;
- bool value_is_deleted = false;
while ((attr_mod = opdata->param.modify.attrMods[i++]) != nullptr) {
- if ((attr_mod->modType == SA_IMM_ATTR_VALUES_DELETE) ||
- (attr_mod->modAttr.attrValues == nullptr)) {
- /* Attribute value is deleted, revert to default value
if applicable*/
- value_is_deleted = true;
- } else {
- /* Attribute value is modified */
- value_is_deleted = false;
- }
+ /* Attribute value removed */
+ if ((attr_mod->modType == SA_IMM_ATTR_VALUES_DELETE) ||
(attr_mod->modAttr.attrValues == nullptr))
+ continue;
+
if (!strcmp(attr_mod->modAttr.attrName, "saAmfSUFailover")) {
- if (value_is_deleted == true)
- continue;
AVD_SU *su =
su_db->find(Amf::to_string(&opdata->objectName));
uint32_t su_failover = *((SaUint32T
*)attr_mod->modAttr.attrValues[0]);
@@ -1403,8 +1396,6 @@ static SaAisErrorT su_ccb_completed_modi
goto done;
}
} else if (!strcmp(attr_mod->modAttr.attrName,
"saAmfSUMaintenanceCampaign")) {
- if (value_is_deleted == true)
- continue;
AVD_SU *su =
su_db->find(Amf::to_string(&opdata->objectName));
if (su->saAmfSUMaintenanceCampaign.length > 0) {
@@ -1414,8 +1405,6 @@ static SaAisErrorT su_ccb_completed_modi
goto done;
}
} else if (!strcmp(attr_mod->modAttr.attrName, "saAmfSUType")) {
- if (value_is_deleted == true)
- continue;
AVD_SU *su;
SaNameT sutype_name = *(SaNameT*)
attr_mod->modAttr.attrValues[0];
su = su_db->find(Amf::to_string(&opdata->objectName));
------------------------------------------------------------------------------
_______________________________________________
Opensaf-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensaf-devel