osaf/services/saf/amf/amfd/cluster.cc        |    4 +
 osaf/services/saf/amf/amfd/csi.cc            |   38 -----
 osaf/services/saf/amf/amfd/imm.cc            |    5 +-
 osaf/services/saf/amf/amfd/include/csi.h     |    1 -
 osaf/services/saf/amf/amfd/include/imm.h     |    5 +-
 osaf/services/saf/amf/amfd/include/sg.h      |    6 +-
 osaf/services/saf/amf/amfd/include/su.h      |    3 +-
 osaf/services/saf/amf/amfd/include/susi.h    |    6 +-
 osaf/services/saf/amf/amfd/include/util.h    |    2 +
 osaf/services/saf/amf/amfd/ndfsm.cc          |   11 +-
 osaf/services/saf/amf/amfd/role.cc           |    6 -
 osaf/services/saf/amf/amfd/sg.cc             |  110 ++++++++++++++-
 osaf/services/saf/amf/amfd/sg_2n_fsm.cc      |    8 +-
 osaf/services/saf/amf/amfd/sg_npm_fsm.cc     |    2 +-
 osaf/services/saf/amf/amfd/sg_nwayact_fsm.cc |    2 +-
 osaf/services/saf/amf/amfd/sgproc.cc         |  140 ++++++++++--------
 osaf/services/saf/amf/amfd/siass.cc          |  204 ++++++++++++++++++--------
 osaf/services/saf/amf/amfd/su.cc             |   46 +++--
 osaf/services/saf/amf/config/amf_classes.xml |   21 ++
 19 files changed, 411 insertions(+), 209 deletions(-)


If there's an admin operation running and at that time cluster goes into 
headless stage,
the normal admin operation sequence is interrupted. Since both SCs are down, 
the SI
assignments at AMFND could be on going or completed during headless period. 
After headless
this admin operation should be continued. This patch series supports the admin 
operation
continuation after headless.

To resume the admin operation after headless, the states need to be restored 
are: SUSI fsm
states, SG fsm states, SI Dependency states (not suppported in this patch), and 
SU operation
list in SG at the time cluster goes headless.

At this moment, the SG fsm states are set variously in each specific SG models. 
Also, the
rule that a SU to be added in SG's operation list is not consistent. A SU is 
added to
operation list after AMFD sends su_si_assign event on this SU in most of the 
places. However,
there're are some scenarios that a SU is added to the list for other purposes. 
These difficulties
make the state logic deduction hard to implemenent.

This patch introduces new RTA states: saAmfSGSuOperationList, saAmfSGFsmState, 
saAmfSISUFsmState
to capture the SG's operation list, SG Fsm state, SUSI fsm state in AMFD's 
memory to IMM during
AMFD's lifetime. If cluster comes back from headless, these RTA will read from 
IMM to restore
states in AMFD's memory. After this patch, if admin operation interrupts to 
headless stage, and
csi callback is responded after headless, the admin operation can continue. The 
other patch
in this series will help admin operation continuation if a csi callback 
completes during 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
@@ -83,6 +83,10 @@ void avd_cluster_tmr_init_evh(AVD_CL_CB 
                        continue;
                }
 
+               if (i_sg->any_assignment_in_progress() == false) {
+                       i_sg->set_fsm_state(AVD_SG_FSM_STABLE);
+               }
+
                if (i_sg->sg_fsm_state == AVD_SG_FSM_STABLE)
                        i_sg->realign(cb, i_sg);
        }
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
@@ -1411,44 +1411,6 @@ bool are_sponsor_csis_assigned_in_su(AVD
 }
 
 /**
- * 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
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
@@ -1588,7 +1588,8 @@ done:
  * @param value
  */
 SaAisErrorT avd_saImmOiRtObjectUpdate_sync(const SaNameT *dn, SaImmAttrNameT 
attributeName,
-       SaImmValueTypeT attrValueType, void *value)
+       SaImmValueTypeT attrValueType, void *value,
+       SaImmAttrModificationTypeT modifyType)
 {
        SaAisErrorT rc;
        SaImmAttrModificationT_2 attrMod;
@@ -1597,7 +1598,7 @@ SaAisErrorT avd_saImmOiRtObjectUpdate_sy
 
        TRACE_ENTER2("'%s' %s", dn->value, attributeName);
 
-       attrMod.modType = SA_IMM_ATTR_VALUES_REPLACE;
+       attrMod.modType = modifyType;
        attrMod.modAttr.attrName = attributeName;
        attrMod.modAttr.attrValuesNumber = 1;
        attrMod.modAttr.attrValueType = attrValueType;
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,7 +184,6 @@ 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/imm.h 
b/osaf/services/saf/amf/amfd/include/imm.h
--- a/osaf/services/saf/amf/amfd/include/imm.h
+++ b/osaf/services/saf/amf/amfd/include/imm.h
@@ -147,10 +147,11 @@ void avd_class_impl_set(const char *clas
  * @return SaAisErrorT
  */
 SaAisErrorT avd_imm_default_OK_completed_cb(CcbUtilOperationData_t *opdata);
+SaAisErrorT avd_saImmOiRtObjectUpdate_sync(const SaNameT *dn,
+       SaImmAttrNameT attributeName, SaImmValueTypeT attrValueType, void 
*value,
+       SaImmAttrModificationTypeT modifyType = SA_IMM_ATTR_VALUES_REPLACE);
 
 extern unsigned int avd_imm_config_get(void);
-extern SaAisErrorT avd_saImmOiRtObjectUpdate_sync(const SaNameT *dn,
-       SaImmAttrNameT attributeName, SaImmValueTypeT attrValueType, void 
*value);
 extern void avd_saImmOiRtObjectUpdate(const SaNameT* dn, const char 
*attributeName,
      SaImmValueTypeT attrValueType, void* value);
 extern void avd_saImmOiRtObjectCreate(const char *className,
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
@@ -185,7 +185,7 @@ public:
         */
        std::vector<AVD_SU*> list_of_su;
        AVD_SU* first_su();
-
+       AVD_SU* get_su_by_name(SaNameT su_name);
        /* the list of service instances in 
         * this group in the descending order 
         * of the rank.
@@ -211,7 +211,6 @@ public:
        
        void add_si(AVD_SI* si);
        void remove_si(AVD_SI* si);
-
        /**
         * Set SG admin state, logs, checkpoints and sends notification
         * @param state
@@ -414,6 +413,7 @@ public:
          */
        bool is_sg_serviceable_outside_ng(const AVD_AMF_NG *ng);
        SaAisErrorT check_sg_stability();
+       bool any_assignment_in_progress();
        bool ng_using_saAmfSGAdminState;
        
        uint32_t term_su_list_in_reverse();
@@ -575,6 +575,8 @@ private:
 #define m_AVD_CLEAR_SG_ADMIN_SI(cb,sg) (sg)->clear_admin_si()
 #define m_AVD_CHK_OPLIST(i_su,flag) (flag) = 
(i_su)->sg_of_su->in_su_oper_list(i_su)
 
+void avd_sg_read_headless_cached_rta(AVD_CL_CB *cb);
+
 extern void avd_sg_delete(AVD_SG *sg);
 extern void avd_sg_db_add(AVD_SG *sg);
 extern void avd_sg_db_remove(AVD_SG *sg);
diff --git a/osaf/services/saf/amf/amfd/include/su.h 
b/osaf/services/saf/amf/amfd/include/su.h
--- a/osaf/services/saf/amf/amfd/include/su.h
+++ b/osaf/services/saf/amf/amfd/include/su.h
@@ -133,8 +133,7 @@ class AVD_SU {
        void shutdown(SaImmOiHandleT immoi_handle, SaInvocationT invocation);
        void lock(SaImmOiHandleT immoi_handle, SaInvocationT invocation,
                SaAmfAdminStateT adm_state);
-       bool any_susi_fsm_in_unasgn();
-       bool any_susi_fsm_in_modify();
+       bool any_susi_in_fsm(uint32_t check_fsm);
        SaAisErrorT check_su_stability();
        uint32_t curr_num_standby_sis();
        uint32_t curr_num_active_sis();
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
@@ -136,8 +136,11 @@ extern AmfDb<std::pair<std::string, uint
    avd_susi_delete(cb,susi,false);\
 }
 
-AVD_SU_SI_REL *avd_susi_create(AVD_CL_CB *cb, AVD_SI *si, AVD_SU *su, 
SaAmfHAStateT state, bool ckpt);
+AVD_SU_SI_REL *avd_susi_create(AVD_CL_CB *cb, AVD_SI *si, AVD_SU *su, 
SaAmfHAStateT state,
+                                               bool ckpt, AVSV_SUSI_ACT 
default_act = AVSV_SUSI_ACT_ASGN);
 AVD_SU_SI_REL *avd_susi_find(AVD_CL_CB *cb, const SaNameT *su_name, const 
SaNameT *si_name);
+void avd_susi_update_fsm(AVD_SU_SI_REL *susi, AVD_SU_SI_STATE new_fsm_state);
+void avd_susi_read_headless_cached_rta(AVD_CL_CB *cb);
 extern void avd_susi_update(AVD_SU_SI_REL *susi, SaAmfHAStateT ha_state);
 
 AVD_SU_SI_REL *avd_su_susi_find(AVD_CL_CB *cb, AVD_SU *su, const SaNameT 
*si_name);
@@ -157,7 +160,6 @@ 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/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
@@ -96,4 +96,6 @@ extern void d2n_msg_free(AVSV_DND_MSG *m
 extern const char* avd_getparent(const char* dn);
 extern bool object_exist_in_imm(const SaNameT *dn);
 extern const char *admin_op_name(SaAmfAdminOperationIdT opid);
+void avsv_sanamet_init_from_association_dn(const SaNameT *haystack, SaNameT 
*dn,
+       const char *needle, const char *parent);
 #endif
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
@@ -53,7 +53,7 @@ void avd_process_state_info_queue(AVD_CL
        AVD_EVT_QUEUE *queue_evt = nullptr;
        /* Counter for Act Amfnd node up message.*/
        static int act_amfnd_node_up_count = 0;
-
+       bool found_state_info = false;
        TRACE_ENTER();
 
        TRACE("queue_size before processing: %lu", (unsigned long) queue_size);
@@ -72,7 +72,7 @@ void avd_process_state_info_queue(AVD_CL
                        AVD_DND_MSG* n2d_msg = queue_evt->evt->info.avnd_msg;
 
                        TRACE("msg_type: %u", n2d_msg->msg_type);
-
+                       found_state_info = true;
                        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);
@@ -124,6 +124,13 @@ void avd_process_state_info_queue(AVD_CL
                        }
                }
        }
+
+       // Read cached rta from Imm
+       // Reading sg must be after reading susi
+       if (found_state_info == true) {
+               avd_susi_read_headless_cached_rta(cb);
+               avd_sg_read_headless_cached_rta(cb);
+       }
 done:
        TRACE("queue_size after processing: %lu", (unsigned long) 
cb->evt_queue.size());
        TRACE_LEAVE();
diff --git a/osaf/services/saf/amf/amfd/role.cc 
b/osaf/services/saf/amf/amfd/role.cc
--- a/osaf/services/saf/amf/amfd/role.cc
+++ b/osaf/services/saf/amf/amfd/role.cc
@@ -227,12 +227,6 @@ uint32_t initialize_for_assignment(cl_cb
                        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 if (ha_state == SA_AMF_HA_STANDBY) {
                rc = avd_standby_role_initialization(cb);
                if (rc != NCSCC_RC_SUCCESS) {
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
@@ -1661,7 +1661,7 @@ void AVD_SG::set_admin_state(SaAmfAdminS
        saflog(LOG_NOTICE, amfSvcUsrName, "%s AdmState %s => %s", name.value,
                   avd_adm_state_name[old_state], avd_adm_state_name[state]);
        saAmfSGAdminState = state;
-       avd_saImmOiRtObjectUpdate(&name,
+       avd_saImmOiRtObjectUpdate(const_cast<SaNameT*>(&name),
                  const_cast<SaImmAttrNameT>("saAmfSGAdminState"), 
SA_IMM_ATTR_SAUINT32T,
                  &saAmfSGAdminState);
        m_AVSV_SEND_CKPT_UPDT_ASYNC_UPDT(avd_cb, this, 
AVSV_CKPT_SG_ADMIN_STATE);
@@ -1678,6 +1678,11 @@ void AVD_SG::set_fsm_state(AVD_SG_FSM_ST
                TRACE("%s sg_fsm_state %u => %u", name.value, sg_fsm_state, 
state);
                sg_fsm_state = state;
                m_AVSV_SEND_CKPT_UPDT_ASYNC_UPDT(avd_cb, this, 
AVSV_CKPT_SG_FSM_STATE);
+               if (avd_cb->scs_absence_max_duration > 0) {
+                       
avd_saImmOiRtObjectUpdate_sync(const_cast<SaNameT*>(&name),
+                                       
const_cast<SaImmAttrNameT>("saAmfSGFsmState"),
+                                       SA_IMM_ATTR_SAUINT32T, &sg_fsm_state);
+               }
        }
 
        if (state == AVD_SG_FSM_STABLE) {
@@ -2043,6 +2048,17 @@ AVD_SU* AVD_SG::first_su()
        }
 }
 
+AVD_SU* AVD_SG::get_su_by_name(SaNameT su_name)
+{
+       for (const auto& su : list_of_su) {
+               if (Amf::to_string(const_cast<SaNameT*>(&su->name)) ==
+                               Amf::to_string(const_cast<SaNameT*>(&su_name))) 
{
+                       return su;
+               }
+       }
+       return nullptr;
+}
+
 uint32_t AVD_SG::curr_assigned_sus() const
 {
        return (std::count_if (list_of_su.cbegin(), list_of_su.cend(),
@@ -2060,3 +2076,95 @@ uint32_t AVD_SG::curr_non_instantiated_s
                [](AVD_SU *su) -> bool { return ((su->list_of_susi == nullptr) 
&&
                        (su->saAmfSUPresenceState == 
SA_AMF_PRESENCE_UNINSTANTIATED));}));      
 }
+
+void avd_sg_read_headless_cached_rta(AVD_CL_CB *cb)
+{
+       SaAisErrorT rc;
+       SaImmSearchHandleT searchHandle;
+       SaImmSearchParametersT_2 searchParam;
+
+       SaNameT sg_dn;
+       AVD_SG *sg;
+       unsigned int num_of_values = 0;
+       const SaImmAttrValuesT_2 **attributes;
+
+       const char *className = "SaAmfSG";
+       const SaImmAttrNameT searchAttributes[] = {
+               const_cast<SaImmAttrNameT>("saAmfSGFsmState"),
+               const_cast<SaImmAttrNameT>("saAmfSGSuOperationList"),
+               NULL
+       };
+
+       TRACE_ENTER();
+
+       osafassert(cb->scs_absence_max_duration > 0);
+
+       searchParam.searchOneAttr.attrName = 
const_cast<SaImmAttrNameT>("SaImmAttrClassName");
+       searchParam.searchOneAttr.attrValueType = SA_IMM_ATTR_SASTRINGT;
+       searchParam.searchOneAttr.attrValue = &className;
+
+       if ((rc = immutil_saImmOmSearchInitialize_2(cb->immOmHandle, NULL, 
SA_IMM_SUBTREE,
+             SA_IMM_SEARCH_ONE_ATTR | SA_IMM_SEARCH_GET_SOME_ATTR, 
&searchParam,
+                 searchAttributes, &searchHandle)) != SA_AIS_OK) {
+
+               LOG_ER("%s: saImmOmSearchInitialize_2 failed: %u", 
__FUNCTION__, rc);
+               goto done;
+       }
+
+       while ((rc = immutil_saImmOmSearchNext_2(searchHandle, &sg_dn,
+                                       (SaImmAttrValuesT_2 ***)&attributes)) 
== SA_AIS_OK) {
+               sg = sg_db->find(Amf::to_string(&sg_dn));
+               if (sg) {
+                       if (sg->sg_ncs_spec == false) {
+                               // Read sg fsm state
+                               rc = 
immutil_getAttr(const_cast<SaImmAttrNameT>("saAmfSGFsmState"),
+                                               attributes, 0, 
&sg->sg_fsm_state);
+                               if (rc == SA_AIS_OK) {
+                                       TRACE("SG'%s', fsm:'%d'", 
Amf::to_string(&sg->name).c_str(),
+                                                       sg->sg_fsm_state);
+                               } else {
+                                       LOG_ER("Failed to read saAmfSGFsmState 
of SG'%s' with error:%d, current fsm:'%d'",
+                                                       
Amf::to_string(&sg->name).c_str(), rc, sg->sg_fsm_state);
+                               }
+                               m_AVSV_SEND_CKPT_UPDT_ASYNC_UPDT(cb, sg, 
AVSV_CKPT_SG_FSM_STATE);
+
+                               // Read sg operation list
+                               if 
(immutil_getAttrValuesNumber(const_cast<SaImmAttrNameT>("saAmfSGSuOperationList"),
 attributes, &num_of_values) == SA_AIS_OK) {
+                                       unsigned int i;
+                                       for (i = 0; i < num_of_values; i++) {
+                                               const SaNameT *su_name = 
immutil_getNameAttr(attributes, "saAmfSGSuOperationList", i);
+                                               AVD_SU* op_su = 
sg->get_su_by_name(*su_name);
+                                               if (op_su) {
+                                                       if 
(op_su->sg_of_su->any_assignment_in_progress()) {
+                                                               TRACE("Found 
and add su in operation list: SU'%s'", Amf::to_string(su_name).c_str());
+                                                               
sg->su_oper_list.push_back(op_su);
+                                                               
m_AVSV_SEND_CKPT_UPDT_ASYNC_ADD(cb, op_su, AVSV_CKPT_AVD_SG_OPER_SU);
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+
+       (void)immutil_saImmOmSearchFinalize(searchHandle);
+
+done:
+    TRACE_LEAVE();
+}
+
+bool AVD_SG::any_assignment_in_progress() {
+       bool pending = false;
+       TRACE_ENTER2("SG:'%s'", Amf::to_string(&name).c_str());
+       for (const auto& su : list_of_su) {
+               if (su->any_susi_in_fsm(AVD_SU_SI_STATE_ASGN) ||
+                       su->any_susi_in_fsm(AVD_SU_SI_STATE_UNASGN) ||
+                       su->any_susi_in_fsm(AVD_SU_SI_STATE_MODIFY)){
+                       pending = true;
+                       break;
+               }
+       }
+       TRACE_LEAVE();
+       return pending;
+}
+
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
@@ -1088,7 +1088,7 @@ uint32_t SG_2N::su_fault_si_oper(AVD_SU 
                                 * Add the SU to the SU operation list.Change 
SG fsm to su_oper.
                                 */
                                l_susi->state = SA_AMF_HA_QUIESCED; 
-                               l_susi->fsm = AVD_SU_SI_STATE_ASGND;
+                               avd_susi_update_fsm(l_susi, 
AVD_SU_SI_STATE_ASGND);
                                m_AVSV_SEND_CKPT_UPDT_ASYNC_UPDT(avd_cb, 
l_susi, AVSV_CKPT_AVD_SI_ASS);
                                avd_gen_su_ha_state_changed_ntf(avd_cb, l_susi);
                                avd_susi_update_assignment_counters(l_susi, 
AVSV_SUSI_ACT_MOD, SA_AMF_HA_QUIESCING, SA_AMF_HA_QUIESCED);
@@ -2958,7 +2958,7 @@ void SG_2N::node_fail_su_oper(AVD_SU *su
                                         * *a_susi->su* starts active 
assignment.
                                         */
                                        
su->set_su_switch(AVSV_SI_TOGGLE_STABLE);
-                                       if 
(a_susi->su->any_susi_fsm_in_modify() == true) {
+                                       if 
(a_susi->su->any_susi_in_fsm(AVD_SU_SI_STATE_MODIFY) == true) {
                                                avd_sg_su_oper_list_add(cb, 
a_susi->su, false);
                                                m_AVD_SET_SG_FSM(cb, 
(su->sg_of_su), AVD_SG_FSM_SG_REALIGN);
                                        }
@@ -4034,8 +4034,8 @@ void SG_2N::ng_admin(AVD_SU *su, AVD_AMF
                if (sg_fsm_state == AVD_SG_FSM_STABLE) {
                        su_admin_down(avd_cb, su, node);
                        //Increment node counter for tracking status of ng 
operation.
-                       if ((su->any_susi_fsm_in_modify() == true) ||
-                                       (su->any_susi_fsm_in_unasgn() == true)) 
{
+                       if ((su->any_susi_in_fsm(AVD_SU_SI_STATE_MODIFY) == 
true) ||
+                                       
(su->any_susi_in_fsm(AVD_SU_SI_STATE_UNASGN) == true)) {
                                node->su_cnt_admin_oper++;
                                TRACE("node:%s, su_cnt_admin_oper:%u", 
node->name.value,
                                                node->su_cnt_admin_oper);
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
@@ -2066,7 +2066,7 @@ uint32_t SG_NPM::susi_sucss_sg_reln(AVD_
                                i_susi = su->sg_of_su->admin_si->list_of_sisu;
 
                        if ((i_susi != AVD_SU_SI_REL_NULL) && (i_susi->fsm != 
AVD_SU_SI_STATE_UNASGN)) {
-                               i_susi->fsm = AVD_SU_SI_STATE_UNASGN;
+                               avd_susi_update_fsm(i_susi, 
AVD_SU_SI_STATE_UNASGN);
                                m_AVSV_SEND_CKPT_UPDT_ASYNC_UPDT(cb, i_susi, 
AVSV_CKPT_AVD_SI_ASS);
                                avd_susi_del_send(i_susi);
                                avd_sg_su_oper_list_add(cb, i_susi->su, false);
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
@@ -1953,7 +1953,7 @@ void SG_NACV::ng_admin(AVD_SU *su, AVD_A
        avd_sg_su_oper_list_add(avd_cb, su, false);
        su->sg_of_su->set_fsm_state(AVD_SG_FSM_SG_REALIGN);
        //Increment node counter for tracking status of ng operation.
-       if (su->any_susi_fsm_in_modify() == true) {
+       if (su->any_susi_in_fsm(AVD_SU_SI_STATE_MODIFY) == true) {
                su->su_on_node->su_cnt_admin_oper++;
                TRACE("node:%s, su_cnt_admin_oper:%u", 
su->su_on_node->name.value,
                                su->su_on_node->su_cnt_admin_oper);
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
@@ -117,7 +117,7 @@ uint32_t avd_new_assgn_susi(AVD_CL_CB *c
                goto done;
        }
 
-       susi->fsm = AVD_SU_SI_STATE_ASGN;
+       avd_susi_update_fsm(susi, AVD_SU_SI_STATE_ASGN);
        susi->state = ha_state;
 
        /* Mark csi to be unassigned to detect duplicate assignment.*/
@@ -710,6 +710,10 @@ void avd_su_oper_state_evh(AVD_CL_CB *cb
        if ((cb->amf_init_tmr.is_active == true) &&
                        (cluster_su_instantiation_done(cb, su) == true)) {
                avd_stop_tmr(cb, &cb->amf_init_tmr);
+
+               if (su->sg_of_su->any_assignment_in_progress() == false) {
+                       su->sg_of_su->sg_fsm_state = AVD_SG_FSM_STABLE;
+               }
                cluster_startup_expiry_event_generate(cb);
        }
 
@@ -870,6 +874,9 @@ void avd_su_oper_state_evh(AVD_CL_CB *cb
                /* if the SU is NCS SU, mark the SU readiness state as in 
service and call
                 * the SG FSM.
                 */
+               if (su->sg_of_su->any_assignment_in_progress() == false) {
+                       su->sg_of_su->sg_fsm_state = AVD_SG_FSM_STABLE;
+               }
                if (su->sg_of_su->sg_ncs_spec == true) {
                        if (su->saAmfSUAdminState == SA_AMF_ADMIN_UNLOCKED) { 
                                
su->set_readiness_state(SA_AMF_READINESS_IN_SERVICE);
@@ -1109,7 +1116,7 @@ void avd_su_si_assign_evh(AVD_CL_CB *cb,
                }
 
                if (su->list_of_susi == AVD_SU_SI_REL_NULL) {
-                       LOG_ER("%s: no susis", __FUNCTION__);
+                       LOG_WA("%s: no susis", __FUNCTION__);
                        goto done;
                }
 
@@ -1169,9 +1176,12 @@ void avd_su_si_assign_evh(AVD_CL_CB *cb,
                /* Now process the acknowledge message based on
                 * Success or failure.
                 */
+               /*
+                * Continue waiting for all pending assignment from headless to 
complete
+                */
                if (n2d_msg->msg_info.n2d_su_si_assign.error == 
NCSCC_RC_SUCCESS) {
                        if (q_flag == false) {
-                               su->sg_of_su->susi_success(cb, su, 
AVD_SU_SI_REL_NULL,
+                                       su->sg_of_su->susi_success(cb, su, 
AVD_SU_SI_REL_NULL,
                                                
n2d_msg->msg_info.n2d_su_si_assign.msg_act,
                                                
n2d_msg->msg_info.n2d_su_si_assign.ha_state);
                        }
@@ -1342,7 +1352,7 @@ void avd_su_si_assign_evh(AVD_CL_CB *cb,
                        }
 
                        if (n2d_msg->msg_info.n2d_su_si_assign.error == 
NCSCC_RC_SUCCESS) {
-                               susi->fsm = AVD_SU_SI_STATE_ASGND;
+                               avd_susi_update_fsm(susi, 
AVD_SU_SI_STATE_ASGND);
                                m_AVSV_SEND_CKPT_UPDT_ASYNC_UPDT(cb, susi, 
AVSV_CKPT_AVD_SI_ASS);
 
                                /* trigger pg upd */
@@ -1372,7 +1382,7 @@ void avd_su_si_assign_evh(AVD_CL_CB *cb,
                        if (n2d_msg->msg_info.n2d_su_si_assign.error == 
NCSCC_RC_SUCCESS) {
                                if (n2d_msg->msg_info.n2d_su_si_assign.ha_state 
== SA_AMF_HA_QUIESCING) {
                                        q_flag = true;
-                                       susi->fsm = AVD_SU_SI_STATE_ASGND;
+                                       avd_susi_update_fsm(susi, 
AVD_SU_SI_STATE_ASGND);
                                        m_AVSV_SEND_CKPT_UPDT_ASYNC_UPDT(cb, 
susi, AVSV_CKPT_AVD_SI_ASS);
                                } else {
                                        if (susi->state == SA_AMF_HA_QUIESCING) 
{
@@ -1383,7 +1393,7 @@ void avd_su_si_assign_evh(AVD_CL_CB *cb,
                                        }
 
                                        /* set the assigned in the SUSIs. */
-                                       susi->fsm = AVD_SU_SI_STATE_ASGND;
+                                       avd_susi_update_fsm(susi, 
AVD_SU_SI_STATE_ASGND);
                                        m_AVSV_SEND_CKPT_UPDT_ASYNC_UPDT(cb, 
susi, AVSV_CKPT_AVD_SI_ASS);
                                }
 
@@ -2048,60 +2058,51 @@ void avd_node_down_appl_susi_failover(AV
        /* If the AvD is in AVD_APP_STATE run through all the application SUs 
and 
         * reassign all the SUSI assignments for the SG of which the SU is a 
member
         */
-
-       if (cb->init_state == AVD_APP_STATE) {
-               for (const auto& i_su : avnd->list_of_su) {
-
-                       /* Unlike active, quiesced and standby HA states, 
assignment counters
-                          in quiescing HA state are updated when AMFD receives 
assignment 
-                          response from AMFND. During nodefailover amfd will 
not receive 
-                          assignment response from AMFND. 
-                          So if any SU is under going modify operation then 
update assignment 
-                          counters for those SUSIs which are in quiescing 
state in the SU.
-                        */ 
-                       for (AVD_SU_SI_REL *susi = i_su->list_of_susi; susi; 
susi = susi->su_next) {
-                               if ((susi->fsm == AVD_SU_SI_STATE_MODIFY) &&
-                                               (susi->state == 
SA_AMF_HA_QUIESCING)) {
-                                       
avd_susi_update_assignment_counters(susi, AVSV_SUSI_ACT_MOD,
-                                                       SA_AMF_HA_QUIESCING, 
SA_AMF_HA_QUIESCED);
-                               }
-                               else if ((susi->fsm == AVD_SU_SI_STATE_MODIFY) 
&&
-                                               (susi->state == 
SA_AMF_HA_ACTIVE)) {
-                                       /* SUSI is undergoing active 
modification. For active state
-                                          saAmfSINumCurrActiveAssignments was 
increased when active
-                                          assignment had been sent. So 
decrement the count in SI before
-                                          deleting the SUSI. */
-                                       susi->si->dec_curr_act_ass();
-                               }
-                               else if ((susi->fsm == AVD_SU_SI_STATE_MODIFY) 
&&
-                                               (susi->state == 
SA_AMF_HA_STANDBY)) {
-                                       /* SUSI is undergoing standby 
modification. For standby state
-                                          saAmfSINumCurrStandbyAssignments was 
increased when standby 
-                                          assignment had been sent. So 
decrement the count in SI before
-                                          deleting the SUSI. */
-                                       susi->si->dec_curr_stdby_ass();
-                               }
-
-
+       TRACE("cb->init_state: %d", cb->init_state);
+       for (const auto& i_su : avnd->list_of_su) {
+               /* Unlike active, quiesced and standby HA states, assignment 
counters
+                  in quiescing HA state are updated when AMFD receives 
assignment
+                  response from AMFND. During nodefailover amfd will not 
receive
+                  assignment response from AMFND.
+                  So if any SU is under going modify operation then update 
assignment
+                  counters for those SUSIs which are in quiescing state in the 
SU.
+                */
+               for (AVD_SU_SI_REL *susi = i_su->list_of_susi; susi; susi = 
susi->su_next) {
+                       if ((susi->fsm == AVD_SU_SI_STATE_MODIFY) &&
+                                       (susi->state == SA_AMF_HA_QUIESCING)) {
+                               avd_susi_update_assignment_counters(susi, 
AVSV_SUSI_ACT_MOD,
+                                               SA_AMF_HA_QUIESCING, 
SA_AMF_HA_QUIESCED);
+                       }
+                       else if ((susi->fsm == AVD_SU_SI_STATE_MODIFY) &&
+                                       (susi->state == SA_AMF_HA_ACTIVE)) {
+                               /* SUSI is undergoing active modification. For 
active state
+                                  saAmfSINumCurrActiveAssignments was 
increased when active
+                                  assignment had been sent. So decrement the 
count in SI before
+                                  deleting the SUSI. */
+                               susi->si->dec_curr_act_ass();
+                       }
+                       else if ((susi->fsm == AVD_SU_SI_STATE_MODIFY) &&
+                                       (susi->state == SA_AMF_HA_STANDBY)) {
+                               /* SUSI is undergoing standby modification. For 
standby state
+                                  saAmfSINumCurrStandbyAssignments was 
increased when standby
+                                  assignment had been sent. So decrement the 
count in SI before
+                                  deleting the SUSI. */
+                               susi->si->dec_curr_stdby_ass();
                        }
 
+               }
                        /* Now analyze the service group for the new HA state
-                        * assignments and send the SU SI assign messages
-                        * accordingly.
-                        */
-                       i_su->sg_of_su->node_fail(cb, i_su);
-
+                * assignments and send the SU SI assign messages
+                * accordingly.
+                */
+               i_su->sg_of_su->node_fail(cb, i_su);
                        /* Free all the SU SI assignments*/ 
-                       i_su->delete_all_susis();
-
+               i_su->delete_all_susis();
                        /* Since a SU has gone out of service relook at the SG 
to
-                        * re instatiate and terminate SUs if needed.
-                        */
-                       avd_sg_app_su_inst_func(cb, i_su->sg_of_su);
-
-               }               /* for (const auto& i_su : avnd->list_of_su) */
-
-       }
+                * re instatiate and terminate SUs if needed.
+                */
+               avd_sg_app_su_inst_func(cb, i_su->sg_of_su);
+       }               /* for (const auto& i_su : avnd->list_of_su) */
 
        /* If this node-failover/nodereboot occurs dueing nodegroup operation 
then check 
           if this leads to completion of operation and try to reply to imm.*/
@@ -2148,8 +2149,15 @@ uint32_t avd_sg_su_oper_list_add(AVD_CL_
        
        su_oper_list.push_back(su);
 
-       if (!ckpt)
+       if (!ckpt) {
+               // Update to IMM if headless is enabled
+               if (cb->scs_absence_max_duration > 0) {
+                       
avd_saImmOiRtObjectUpdate_sync(const_cast<SaNameT*>(&su->sg_of_su->name),
+                                       
const_cast<SaImmAttrNameT>("saAmfSGSuOperationList"),
+                                       SA_IMM_ATTR_SANAMET, &su->name, 
SA_IMM_ATTR_VALUES_ADD);
+               }
                m_AVSV_SEND_CKPT_UPDT_ASYNC_ADD(cb, su, 
AVSV_CKPT_AVD_SG_OPER_SU);
+       }
 
 done:
        TRACE_LEAVE();
@@ -2188,14 +2196,22 @@ uint32_t avd_sg_su_oper_list_del(AVD_CL_
        }
        
        if (elem == su_oper_list.end()) {
-               LOG_ER("%s: su not found", __FUNCTION__);
+               LOG_WA("%s: su not found", __FUNCTION__);
                rc = NCSCC_RC_FAILURE;
                goto done;
        }       
 
        su_oper_list.erase(elem);
-       if (!ckpt)
+
+       if (!ckpt) {
+               // Update to IMM if headless is enabled
+               if (cb->scs_absence_max_duration > 0) {
+                       
avd_saImmOiRtObjectUpdate_sync(const_cast<SaNameT*>(&su->sg_of_su->name),
+                                       
const_cast<SaImmAttrNameT>("saAmfSGSuOperationList"),
+                                       SA_IMM_ATTR_SANAMET, &su->name, 
SA_IMM_ATTR_VALUES_DELETE);
+               }
                m_AVSV_SEND_CKPT_UPDT_ASYNC_RMV(cb, su, 
AVSV_CKPT_AVD_SG_OPER_SU);
+       }
        
 done:
        TRACE_LEAVE2("rc:%u", rc);
@@ -2248,7 +2264,7 @@ uint32_t avd_sg_su_si_mod_snd(AVD_CL_CB 
                old_state = i_susi->fsm;
 
                i_susi->state = state;
-               i_susi->fsm = AVD_SU_SI_STATE_MODIFY;
+               avd_susi_update_fsm(i_susi, AVD_SU_SI_STATE_MODIFY);
                m_AVSV_SEND_CKPT_UPDT_ASYNC_UPDT(cb, i_susi, 
AVSV_CKPT_AVD_SI_ASS);
                avd_susi_update_assignment_counters(i_susi, AVSV_SUSI_ACT_MOD, 
old_ha_state, state);
 
@@ -2270,7 +2286,7 @@ uint32_t avd_sg_su_si_mod_snd(AVD_CL_CB 
                        }
 
                        i_susi->state = old_ha_state;
-                       i_susi->fsm = old_state;
+                       avd_susi_update_fsm(i_susi, old_state);
                        m_AVSV_SEND_CKPT_UPDT_ASYNC_UPDT(cb, i_susi, 
AVSV_CKPT_AVD_SI_ASS);
                        i_susi = i_susi->su_next;
                }
@@ -2344,7 +2360,7 @@ uint32_t avd_sg_su_si_del_snd(AVD_CL_CB 
        while (i_susi != AVD_SU_SI_REL_NULL) {
                old_state = i_susi->fsm;
                if (i_susi->fsm != AVD_SU_SI_STATE_UNASGN) {
-                       i_susi->fsm = AVD_SU_SI_STATE_UNASGN;
+                       avd_susi_update_fsm(i_susi, AVD_SU_SI_STATE_UNASGN);
                        m_AVSV_SEND_CKPT_UPDT_ASYNC_UPDT(cb, i_susi, 
AVSV_CKPT_AVD_SI_ASS);
                        /* Update the assignment counters */
                        avd_susi_update_assignment_counters(i_susi, 
AVSV_SUSI_ACT_DEL, static_cast<SaAmfHAStateT>(0), 
static_cast<SaAmfHAStateT>(0));
@@ -2359,7 +2375,7 @@ uint32_t avd_sg_su_si_del_snd(AVD_CL_CB 
                LOG_ER("%s: avd_snd_susi_msg failed, %s", __FUNCTION__, 
su->name.value);
                i_susi = su->list_of_susi;
                while (i_susi != AVD_SU_SI_REL_NULL) {
-                       i_susi->fsm = old_state;
+                       avd_susi_update_fsm(i_susi, old_state);
                        m_AVSV_SEND_CKPT_UPDT_ASYNC_UPDT(cb, i_susi, 
AVSV_CKPT_AVD_SI_ASS);
                        i_susi = i_susi->su_next;
                }
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
@@ -45,15 +45,21 @@
  * @param si_dn
  * @param su_dn
  */
-static void avd_create_susi_in_imm(SaAmfHAStateT ha_state,
-       const SaNameT *si_dn, const SaNameT *su_dn)
+static void avd_create_susi_in_imm(AVD_SU_SI_REL* susi)
 {
        SaNameT dn;
        SaAmfHAReadinessStateT saAmfSISUHAReadinessState =
                        SA_AMF_HARS_READY_FOR_ASSIGNMENT;
+
        void *arr1[] = { &dn };
-       void *arr2[] = { &ha_state };
+       void *arr2[] = { &susi->state };
        void *arr3[] = { &saAmfSISUHAReadinessState };
+
+       uint32_t fsm = 0;
+       if (avd_cb->scs_absence_max_duration > 0)
+               fsm = susi->fsm;
+
+       void *arr4[] = { &fsm };
        const SaImmAttrValuesT_2 attr_safSISU = {
                        const_cast<SaImmAttrNameT>("safSISU"),
                        SA_IMM_ATTR_SANAMET, 1, arr1
@@ -66,15 +72,21 @@ static void avd_create_susi_in_imm(SaAmf
                        const_cast<SaImmAttrNameT>("saAmfSISUHAReadinessState"),
                        SA_IMM_ATTR_SAUINT32T, 1, arr3
        };
+       const SaImmAttrValuesT_2 attr_saAmfSISUFsmState = {
+                       const_cast<SaImmAttrNameT>("saAmfSISUFsmState"),
+                       SA_IMM_ATTR_SAUINT32T, 1, arr4
+       };
+
        const SaImmAttrValuesT_2 *attrValues[] = {
                        &attr_safSISU,
                        &attr_saAmfSISUHAState,
                        &attr_saAmfSISUHAReadinessState,
+                       &attr_saAmfSISUFsmState,
                        nullptr
        };
 
-       avsv_create_association_class_dn(su_dn, nullptr, "safSISU", &dn);
-       avd_saImmOiRtObjectCreate("SaAmfSIAssignment", si_dn, attrValues);
+       avsv_create_association_class_dn(&susi->su->name, nullptr, "safSISU", 
&dn);
+       avd_saImmOiRtObjectCreate("SaAmfSIAssignment", &susi->si->name, 
attrValues);
 }
 
 /** Delete an SaAmfSIAssignment from IMM
@@ -121,6 +133,120 @@ void avd_susi_update(AVD_SU_SI_REL *susi
        }
 }
 
+/**
+ * Update an saAmfSISUFsmState runtime object in IMM.
+ * @param susi
+ * @param new_fsm_state
+ */
+void avd_susi_update_fsm(AVD_SU_SI_REL *susi, AVD_SU_SI_STATE new_fsm_state)
+{
+    SaNameT dn;
+
+    avsv_create_association_class_dn(&susi->su->name, &susi->si->name, 
"safSISU", &dn);
+    TRACE_ENTER2("SISU:'%s', old fsm state: %d, new fsm state: %d",
+               dn.value, susi->fsm, new_fsm_state);
+    if (susi->fsm != new_fsm_state) {
+       susi->fsm = new_fsm_state;
+               if (avd_cb->scs_absence_max_duration > 0) {
+                       avd_saImmOiRtObjectUpdate(&dn, "saAmfSISUFsmState",
+                               SA_IMM_ATTR_SAUINT32T, &susi->fsm);
+               }
+    }
+    TRACE_LEAVE();
+}
+
+/**
+ * Read an saAmfSISUFsmState runtime object from IMM.
+ * @param susi
+ */
+void avd_susi_read_headless_cached_rta(AVD_CL_CB *cb)
+{
+       SaAisErrorT rc;
+       SaImmSearchHandleT searchHandle;
+       SaImmSearchParametersT_2 searchParam;
+
+       SaNameT dn, su_name, si_name;
+       const SaImmAttrValuesT_2 **attributes;
+       AVD_SU_SI_REL *susi = nullptr;
+
+       const char *className = "SaAmfSIAssignment";
+       const SaImmAttrNameT siass_attributes[] = {
+               const_cast<SaImmAttrNameT>("safSISU"),
+               const_cast<SaImmAttrNameT>("saAmfSISUFsmState"),
+               NULL
+       };
+
+       TRACE_ENTER();
+
+       osafassert(cb->scs_absence_max_duration > 0);
+
+       searchParam.searchOneAttr.attrName = 
const_cast<SaImmAttrNameT>("SaImmAttrClassName");
+       searchParam.searchOneAttr.attrValueType = SA_IMM_ATTR_SASTRINGT;
+       searchParam.searchOneAttr.attrValue = &className;
+
+       if ((rc = immutil_saImmOmSearchInitialize_2(cb->immOmHandle, NULL, 
SA_IMM_SUBTREE,
+             SA_IMM_SEARCH_ONE_ATTR | SA_IMM_SEARCH_GET_SOME_ATTR, 
&searchParam,
+                 siass_attributes, &searchHandle)) != SA_AIS_OK) {
+
+               LOG_ER("%s: saImmOmSearchInitialize_2 failed: %u", 
__FUNCTION__, rc);
+               goto done;
+       }
+
+       while ((rc = immutil_saImmOmSearchNext_2(searchHandle, &dn,
+                                       (SaImmAttrValuesT_2 ***)&attributes)) 
== SA_AIS_OK) {
+               //TODO: to be refined after long DN
+               si_name.length = sprintf((char*)si_name.value, "%s",
+                               strstr((char*)dn.value, "safSi"));
+               assert(si_name.length > 0);
+               AVD_SI *si = si_db->find(Amf::to_string(&si_name));
+               osafassert(si);
+
+               avsv_sanamet_init_from_association_dn(&dn, &su_name, "safSu", 
(char*)si->name.value);
+               AVD_SU *su = su_db->find(Amf::to_string(&su_name));
+               osafassert(su);
+               susi = avd_su_susi_find(cb, su, &si->name);
+
+               // Update headless susi
+               if (susi) {
+                       // restore susi fsm
+                       rc = immutil_getAttr("saAmfSISUFsmState", attributes, 
0, &susi->fsm);
+                       if (rc == SA_AIS_OK) {
+                               TRACE("SISU:'%s', fsm:'%d'", 
Amf::to_string(&dn).c_str(), susi->fsm);
+                       } else {
+                               LOG_ER("SISU:'%s', current fsm:'%d', rc:'%d'", 
Amf::to_string(&dn).c_str(),
+                                               susi->fsm, rc);
+                       }
+                       m_AVSV_SEND_CKPT_UPDT_ASYNC_UPDT(cb, susi, 
AVSV_CKPT_AVD_SI_ASS);
+                       // restore assignment counter
+                       if (susi->fsm == AVD_SU_SI_STATE_ASGN || susi->fsm == 
AVD_SU_SI_STATE_ASGND ||
+                               susi->fsm == AVD_SU_SI_STATE_MODIFY) {
+                               if (susi->state == SA_AMF_HA_ACTIVE || 
susi->state == SA_AMF_HA_QUIESCING) {
+                                       su->inc_curr_act_si();
+                                       susi->si->inc_curr_act_ass();
+                               } else if (susi->state == SA_AMF_HA_STANDBY) {
+                                       su->inc_curr_stdby_si();
+                                       susi->si->inc_curr_stdby_ass();
+                               }
+                       }
+                       if (susi->si->saAmfSIAdminState == SA_AMF_ADMIN_LOCKED 
||
+                               susi->si->saAmfSIAdminState == 
SA_AMF_ADMIN_SHUTTING_DOWN) {
+                               if (susi->fsm == AVD_SU_SI_STATE_MODIFY &&
+                                       (susi->state == SA_AMF_HA_QUIESCED || 
susi->state == SA_AMF_HA_QUIESCING)) {
+                                               m_AVD_SET_SG_ADMIN_SI(cb, si);
+                               }
+                       }
+               } else {
+                       // This susi does not exist after headless, but it's 
still in IMM
+                       // delete it for now
+                       avd_saImmOiRtObjectDelete(&dn);
+               }
+       }
+
+       (void)immutil_saImmOmSearchFinalize(searchHandle);
+
+done:
+    TRACE_LEAVE();
+}
 /*****************************************************************************
  * Function: avd_susi_create
  *
@@ -138,7 +264,8 @@ void avd_susi_update(AVD_SU_SI_REL *susi
  * 
  **************************************************************************/
 
-AVD_SU_SI_REL *avd_susi_create(AVD_CL_CB *cb, AVD_SI *si, AVD_SU *su, 
SaAmfHAStateT state, bool ckpt)
+AVD_SU_SI_REL *avd_susi_create(AVD_CL_CB *cb, AVD_SI *si, AVD_SU *su, 
SaAmfHAStateT state,
+                                       bool ckpt, AVSV_SUSI_ACT default_act)
 {
        AVD_SU_SI_REL *su_si, *p_su_si, *i_su_si;
        AVD_SU *curr_su = 0;
@@ -243,9 +370,9 @@ AVD_SU_SI_REL *avd_susi_create(AVD_CL_CB
 done:
        //ADD susi in imm job queue at both standby and active amfd.
        if (su_si != nullptr)
-               avd_create_susi_in_imm(state, &si->name, &su->name);
-       if ((ckpt == false) && (su_si != nullptr)) {
-               avd_susi_update_assignment_counters(su_si, AVSV_SUSI_ACT_ASGN, 
state, state);
+               avd_create_susi_in_imm(su_si);
+       if ((ckpt == false) && (su_si != nullptr) && default_act != 
AVSV_SUSI_ACT_BASE) {
+               avd_susi_update_assignment_counters(su_si, default_act, state, 
state);
                avd_gen_su_ha_state_changed_ntf(cb, su_si);
        }
 
@@ -513,13 +640,13 @@ uint32_t avd_susi_mod_send(AVD_SU_SI_REL
        old_state = susi->state;
        old_fsm_state = susi->fsm;
        susi->state = ha_state;
-       susi->fsm = AVD_SU_SI_STATE_MODIFY;
+       avd_susi_update_fsm(susi, AVD_SU_SI_STATE_MODIFY);
        rc = avd_snd_susi_msg(avd_cb, susi->su, susi, AVSV_SUSI_ACT_MOD, false, 
nullptr);
        if (NCSCC_RC_SUCCESS != rc) {
                LOG_NO("role modification msg send failed %s:%u: SU:%s SI:%s", 
__FILE__,__LINE__,
                        susi->su->name.value,susi->si->name.value);
                susi->state = old_state;
-               susi->fsm = old_fsm_state;
+               avd_susi_update_fsm(susi, old_fsm_state);
                goto done;
        }
        /* Update the assignment counters */
@@ -552,19 +679,17 @@ uint32_t avd_susi_del_send(AVD_SU_SI_REL
        TRACE_ENTER2("SI '%s', SU '%s' ", susi->si->name.value, 
susi->su->name.value);
 
        old_fsm_state = susi->fsm;
-       susi->fsm = AVD_SU_SI_STATE_UNASGN;
-
+       avd_susi_update_fsm(susi, AVD_SU_SI_STATE_UNASGN);
        avd_snd_susi_msg(avd_cb, susi->su, susi, AVSV_SUSI_ACT_DEL, false, 
nullptr);
        if (NCSCC_RC_SUCCESS != rc) {
                LOG_NO("susi del msg snd failed %s:%u: SU:%s SI:%s", 
__FILE__,__LINE__,
                                susi->su->name.value,susi->si->name.value);
-               susi->fsm = old_fsm_state;
+               avd_susi_update_fsm(susi, old_fsm_state);
                goto done;
        }
        /* Update the assignment counters */
        avd_susi_update_assignment_counters(susi, AVSV_SUSI_ACT_DEL, 
static_cast<SaAmfHAStateT>(0), static_cast<SaAmfHAStateT>(0));
 
-
        /* Checkpointing has to be done after getting response, will take care 
subsequently */
        m_AVSV_SEND_CKPT_UPDT_ASYNC_UPDT(avd_cb, susi, AVSV_CKPT_AVD_SI_ASS);
 
@@ -777,44 +902,6 @@ done:
 }
 
 /**
- * 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
@@ -877,19 +964,14 @@ SaAisErrorT avd_susi_recreate(AVSV_N2D_N
 
                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);
+                       susi = avd_susi_create(avd_cb, si, su, ha_state, false, 
AVSV_SUSI_ACT_BASE);
                        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();
-               }
-                su->saAmfSUHostedByNode = node->name;
-                avd_saImmOiRtObjectUpdate(&su->name, "saAmfSUHostedByNode",
+               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);
        }
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
@@ -2066,7 +2066,7 @@ void AVD_SU::set_all_susis_assigned_quie
        for (; susi != nullptr; susi = susi->su_next) {
                if (susi->fsm != AVD_SU_SI_STATE_UNASGN) {
                        susi->state = SA_AMF_HA_QUIESCED;
-                       susi->fsm = AVD_SU_SI_STATE_ASGND;
+                       avd_susi_update_fsm(susi, AVD_SU_SI_STATE_ASGND);
                        m_AVSV_SEND_CKPT_UPDT_ASYNC_UPDT(avd_cb, susi, 
AVSV_CKPT_AVD_SI_ASS);
                        avd_gen_su_ha_state_changed_ntf(avd_cb, susi);
                        avd_susi_update_assignment_counters(susi, 
AVSV_SUSI_ACT_MOD,
@@ -2085,7 +2085,7 @@ void AVD_SU::set_all_susis_assigned(void
 
        for (; susi != nullptr; susi = susi->su_next) {
                if (susi->fsm != AVD_SU_SI_STATE_UNASGN) {
-                       susi->fsm = AVD_SU_SI_STATE_ASGND;
+                       avd_susi_update_fsm(susi, AVD_SU_SI_STATE_ASGND);
                        m_AVSV_SEND_CKPT_UPDT_ASYNC_UPDT(avd_cb, susi, 
AVSV_CKPT_AVD_SI_ASS);
                        avd_pg_susi_chg_prc(avd_cb, susi);
                }
@@ -2293,28 +2293,30 @@ void AVD_SU::complete_admin_op(SaAisErro
        }
 }
 /**
- * @brief    Checks if modification of assignment is sent for any SUSI in SU.
- * @result   true/false  
+ * @brief    Checks if assignment is under specific fsm state
+ *           . If any assignment's fsm is AVD_SU_SI_STATE_UNASGN,
+ *           deletion of assignment has sent to amfnd.
+ *           . If any assignment's fsm is AVD_SU_SI_STATE_MODIFY,
+ *           modification of assignment has sent to amfnd.
+ *           . If any assignment's fsm is AVD_SU_SI_STATE_ASGN,
+ *           creation of assignment has sent to amfnd.
+ * @param    @check_fsm: to-be-check fsm state
+ * @result   true/false
  */
-bool AVD_SU::any_susi_fsm_in_modify()
+bool AVD_SU::any_susi_in_fsm(uint32_t check_fsm)
 {
-        for (AVD_SU_SI_REL *susi = list_of_susi; susi; susi = susi->su_next) {
-                if (susi->fsm == AVD_SU_SI_STATE_MODIFY)
-                        return true;
-        }
-        return false;
-}
-/**
- * @brief    Checks if deletion of assignment is sent for any SUSI in SU.
- * @result   true/false  
- */
-bool AVD_SU::any_susi_fsm_in_unasgn()
-{
-        for (AVD_SU_SI_REL *susi = list_of_susi; susi; susi = susi->su_next) {
-                if (susi->fsm == AVD_SU_SI_STATE_UNASGN)
-                        return true;
-        }
-        return false;
+       TRACE_ENTER2("SU:'%s'", Amf::to_string(&name).c_str());
+       bool rc = false;
+       for (AVD_SU_SI_REL *susi = list_of_susi; susi && rc == false;
+                       susi = susi->su_next) {
+               if (susi->fsm == check_fsm) {
+                       rc = true;
+                       TRACE("SUSI:'%s,%s', fsm:'%d'", 
Amf::to_string(&susi->su->name).c_str(),
+                                       
Amf::to_string(&susi->si->name).c_str(), susi->fsm);
+               }
+       }
+       TRACE_LEAVE();
+       return rc;
 }
 /**
  * @brief  Verify if SU is stable for admin operation on any higher 
diff --git a/osaf/services/saf/amf/config/amf_classes.xml 
b/osaf/services/saf/amf/config/amf_classes.xml
--- a/osaf/services/saf/amf/config/amf_classes.xml
+++ b/osaf/services/saf/amf/config/amf_classes.xml
@@ -320,6 +320,20 @@
                        <type>SA_UINT32_T</type>
                        <category>SA_RUNTIME</category>
                </attr>
+               <attr>
+                       <name>saAmfSGSuOperationList</name>
+                       <type>SA_NAME_T</type>
+                       <category>SA_RUNTIME</category>
+                       <flag>SA_MULTI_VALUE</flag>
+                       <flag>SA_CACHED</flag>
+               </attr>
+               <attr>
+                       <name>saAmfSGFsmState/name>
+                       <type>SA_UINT32_T</type>
+                       <category>SA_RUNTIME</category>
+                       <flag>SA_CACHED</flag>
+                       <default-value>0</default-value>
+               </attr>
        </class>
        <class name="SaAmfSGType">
                <category>SA_CONFIG</category>
@@ -733,6 +747,13 @@
                        <category>SA_RUNTIME</category>
                        <flag>SA_CACHED</flag>
                </attr>
+               <attr>
+                       <name>saAmfSISUFsmState</name>
+                       <type>SA_UINT32_T</type>
+                       <category>SA_RUNTIME</category>
+                       <flag>SA_CACHED</flag>
+                       <default-value>0</default-value>
+               </attr>
        </class>
        <class name="SaAmfSvcTypeCSTypes">
                <category>SA_CONFIG</category>


------------------------------------------------------------------------------
_______________________________________________
Opensaf-devel mailing list
Opensaf-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to