Hi,

I made a mistake in rebase the patch, that I reverted fix of #1595 (the 
last diff)
I'll remove that last diff in next version.

Thanks,
Minh

On 25/02/16 19:44, Minh Hon Chau wrote:
>   osaf/services/saf/amf/amfd/cluster.cc            |   48 +++-
>   osaf/services/saf/amf/amfd/comp.cc               |    8 +-
>   osaf/services/saf/amf/amfd/csi.cc                |  105 +++++++
>   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          |    1 -
>   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/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               |   17 +-
>   osaf/services/saf/amf/amfd/sgproc.cc             |   47 ++-
>   osaf/services/saf/amf/amfd/si.cc                 |   43 ++-
>   osaf/services/saf/amf/amfd/siass.cc              |  121 ++++++++
>   osaf/services/saf/amf/amfd/su.cc                 |   19 +-
>   27 files changed, 911 insertions(+), 66 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
>
> 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);
> @@ -80,13 +82,57 @@ void avd_cluster_tmr_init_evh(AVD_CL_CB
>               if ((i_sg->list_of_su.empty() == true) || (i_sg->sg_ncs_spec == 
> true)) {
>                       continue;
>               }
> -             i_sg->realign(cb, i_sg);
> +
> +             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::avd_comp_pres_state_set(S
>                               node->name.value);
>               LOG_NO("Node Failfast for '%s' as '%s' enters Term/Inst Failed 
> state",
>                               node->name.value,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
> @@ -1410,3 +1410,108 @@ 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
> +             
> comp->avd_comp_oper_state_set(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
> +             
> comp->avd_comp_pres_state_set(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();}
> +   typename AmfDbMap::size_type 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
> @@ -38,7 +38,7 @@
>   #include "role.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
> @@ -593,5 +593,4 @@ extern uint32_t sg_instantiated_su_count
>   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);
>   
> -
>   #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
> @@ -140,6 +140,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();
>           const AVD_SIRANKEDSU *get_si_ranked_su(const std::string &su_name) 
> const;
> 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/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 auto 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);
>       }
> @@ -161,11 +162,11 @@ AVD_AVND::~AVD_AVND() {
>   //
>   AVD_AVND *avd_node_new(const SaNameT *dn)
>   {
> -  AVD_AVND *node;
> -
> -  node = new AVD_AVND(dn);
> -
> -  return node;
> +     AVD_AVND *node;
> +     node = new AVD_AVND(dn);
> +     node->node_up_msg_count = 0;
> +     node->reboot = false;
> +     return node;
>   }
>   
>   void avd_node_delete(AVD_AVND *node)
> @@ -409,8 +410,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/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);
>   
> @@ -288,11 +288,11 @@ static void su_try_repair(const AVD_SU *
>                       (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);
> +                             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);
> +             saflog(LOG_NOTICE, amfSvcUsrName, "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
> @@ -614,6 +614,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:
> @@ -653,6 +657,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
>       };
>   
> @@ -1273,8 +1278,6 @@ void AVD_SI::update_ass_state()
>               if (saAmfSINumCurrActiveAssignments == 0) {
>                       newState = SA_AMF_ASSIGNMENT_UNASSIGNED;
>               } else {
> -                     osafassert(saAmfSINumCurrActiveAssignments == 1);
> -                     osafassert(saAmfSINumCurrStandbyAssignments == 0);
>                       newState = SA_AMF_ASSIGNMENT_FULLY_ASSIGNED;
>               }
>               break;
> @@ -1294,21 +1297,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",
> @@ -1499,4 +1495,29 @@ const AVD_SIRANKEDSU *AVD_SI::get_si_ran
>     }
>   
>     return sirankedsu;
> +}
> +
> +/*
> + * @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);
> +             }
> +     }
>   }
> \ No newline at end of file
> 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,124 @@ 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
> +             // . saAmfSUHostedByNode does not need to update since mapping
> +             //   su to node should reserve the same order
> +             // . 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();
> +             }
> +
> +             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));
>


------------------------------------------------------------------------------
Site24x7 APM Insight: Get Deep Visibility into Application Performance
APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
Monitor end-to-end web transactions and take corrective actions now
Troubleshoot faster and improve end-user experience. Signup Now!
http://pubads.g.doubleclick.net/gampad/clk?id=272487151&iu=/4140
_______________________________________________
Opensaf-devel mailing list
Opensaf-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to