Ack. /Thanks HansN

-----Original Message-----
From: praveen.malv...@oracle.com [mailto:praveen.malv...@oracle.com] 
Sent: den 2 mars 2015 14:35
To: Hans Nordebäck; nagendr...@oracle.com; Bertil Engelholm; 
mathi.naic...@oracle.com
Cc: opensaf-devel@lists.sourceforge.net
Subject: [PATCH 1 of 7] amfd : support shutdown, lock and unlock for 2N, NoRed 
and NWay_Active on NG[#1235]

 osaf/services/saf/amf/amfd/comp.cc           |   14 +
 osaf/services/saf/amf/amfd/include/comp.h    |    1 +
 osaf/services/saf/amf/amfd/include/node.h    |   16 +-
 osaf/services/saf/amf/amfd/include/sg.h      |   24 +-
 osaf/services/saf/amf/amfd/include/su.h      |    3 +
 osaf/services/saf/amf/amfd/node.cc           |   17 +
 osaf/services/saf/amf/amfd/nodegroup.cc      |  414 ++++++++++++++++++++++++++-
 osaf/services/saf/amf/amfd/role.cc           |   17 +-
 osaf/services/saf/amf/amfd/sg.cc             |   82 +++++
 osaf/services/saf/amf/amfd/sgproc.cc         |  122 +++++++-
 osaf/services/saf/amf/amfd/su.cc             |   72 ++++-
 osaf/services/saf/amf/config/amf_classes.xml |    8 +
 12 files changed, 770 insertions(+), 20 deletions(-)


Description of important changes in files:
*)comp.cc:
        -utility function to check if any admin operation is going on component.
*)node.cc:
        -A node can belong to several nodegroups. A utility function
         is added to check if all the nodegroups of a node are unlocked.
         If any nodegroup of node is not unlocked then SUs on any node
         of the nodegroup cannot be assigned any role irrespective of node
         admin state.
*)nodegroup.cc:
        -Support for saAmfNGAdminState.
        -Support for shutdown, lock and unlock operation for 2N, NoRed and 
NWay_Active models.
        -Shutdown and lock operation executes parallely on all the nodes.
         Individual nodes also moves to LOCKED state along with nodegroup
         during shutdown and lock operation.
        -Before accepting any of the three supported operations, AMF verifies
         if operation could be executed. AMF rejects operation on following 
conditionsi:
            --If any AMF entity deployed on anyone of nodesis unstable.
            --If a node contains a SU of NWay or NpM red models.
         Also because of shutdown or lock operation if there is going to be 
complete
         service outage in a SG on the nodegroup, AMF throws only syslogs a 
notice, but
         operation will continue.
        -For shutdown and lock operation, AMF picks each node of nodegroup and 
it calls
         nodegroup admin operation handler (ng_admin()) for each SU of that 
node. This
         handler is written for the presently supported red models in 
sg_2n_fsm.cc,
         sg_nored_fsm.cc and sg_nwayact_fsm.cc.
        -For unlock operation, AMF unlocks all the nodes and enables hosted 
SUs.It then
         calls assignment algorithm for the red model to which SU belongs.
         Thus SUs will be assigned according to their ranks.
*)role.cc:
       -If controller switchover occurs when any admin operation is going
        on the nodegroup then AMF clears all the admin operation related
        parameters.

*)sg.cc:
        -Member function (is_sg_assigned_only_in_ng()) to check if SG has
         assignments only on the nodes of nodegroup.
        -Member function (check_sg_stability()) to check if any admin
         operation is going on SG.
        -Member function (is_sg_serviceable_outside_ng()) to check SG will
         have assignments outside the nodegroup after completion of shutdown
         or lock operation.
*)sgproc.cc:
        -Whenever AMFD gets any assignment response from AMFND, it run SG FSM
         for that SU. After this AMF evaluates if it has to respond to IMM for
         pending admin operationon AMF entities.process_su_si_response_for_ng()
         does same functionality for nodegroup. This function also moves
         individual nodes and nodegroup from shutting_down to locked state.
*)su.cc:
        -SU inservice availabilty c and SU instantiability criteria also 
includes
        nodegroup admin state check.
        -Member functions (any_susi_fsm_in_<*>())to check if any SUSI of SU is 
undergoing
        modification or removal of assignments.
        -Member function (check_su_stability()) to  check if any admin
         operation is going on SG.

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
@@ -1574,3 +1574,17 @@ bool comp_is_preinstantiable(const AVD_C
                        (category == 
AVSV_COMP_TYPE_PROXIED_LOCAL_PRE_INSTANTIABLE) ||
                        (category == AVSV_COMP_TYPE_EXTERNAL_PRE_INSTANTIABLE));
 }
+
+/**
+ * @brief  Verify if component is undergoing any admin operation.
+ * @param  ptr to component(AVD_COMP).
+ * @Return SA_AIS_OK/SA_AIS_ERR_TRY_AGAIN.
+ */
+SaAisErrorT check_comp_stability(const AVD_COMP *comp) {
+        if (comp->admin_pend_cbk.invocation != 0) {
+                LOG_NO("Component undergoing admin operation '%s'", 
comp->comp_info.name.value);
+                return SA_AIS_ERR_TRY_AGAIN;
+        }
+        return SA_AIS_OK;
+}
diff --git a/osaf/services/saf/amf/amfd/include/comp.h 
b/osaf/services/saf/amf/amfd/include/comp.h
--- a/osaf/services/saf/amf/amfd/include/comp.h
+++ b/osaf/services/saf/amf/amfd/include/comp.h
@@ -237,5 +237,6 @@ extern AVD_COMPCS_TYPE * avd_compcstype_  extern void 
avd_compcstype_constructor(void);  extern AVD_COMP 
*avd_comp_get_or_create(const SaNameT *dn);  bool comp_is_preinstantiable(const 
AVD_COMP *comp);
+extern SaAisErrorT check_comp_stability(const AVD_COMP*);
 
 #endif
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
@@ -64,7 +64,7 @@ typedef struct avd_fail_over_node {
 
        SaClmNodeIdT node_id;
 } AVD_FAIL_OVER_NODE;
-
+class AVD_AMF_NG;
 /* Availability directors Node Director structure(AVD_AVND): 
  * This data structure lives in the AvD and reflects data points
  * associated with the AvD's remote, distributed AvNDs. In addition @@ -136,6 
+136,7 @@ typedef struct avd_avnd_tag {
        SaInvocationT clm_pend_inv; /* pending response for any clm track cb */
        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.*/        
 } AVD_AVND;
 
 bool operator<(const AVD_AVND& lhs, const AVD_AVND& rhs); @@ -160,8 +161,16 @@ 
public:
 
        struct avd_ng_tag *cluster_list_ng_next;
        struct avd_cluster_tag *ng_on_cluster;
+       SaAmfAdminStateT  saAmfNGAdminState;
+       AVD_ADMIN_OPER_CBK admin_ng_pend_cbk;   /*to store any pending admin op
+                                                 callbacks on this node group*/
+       std::set<std::string> node_oper_list; /* list of nodes impacted because 
of 
+                                                node group admin op */
+       uint32_t oper_list_size() const {
+               return node_oper_list.size();
+       }
 };
-
+extern AmfDb<std::string, AVD_AMF_NG> *nodegroup_db;
 #define AVD_AVND_NULL     ((AVD_AVND *)0)
 
 #define m_AVD_SET_AVND_RCV_ID(cb,node,rcvid) {\ @@ -220,4 +229,7 @@ extern 
bool node_in_nodegroup(const std:
 /* AMF Node SW Bundle */
 extern void avd_nodeswbundle_constructor(void);
 
+extern void ng_complete_admin_op(AVD_AMF_NG *ng, SaAisErrorT result); 
+extern void avd_ng_admin_state_set(AVD_AMF_NG* ng, SaAmfAdminStateT 
+state); extern bool are_all_ngs_in_unlocked_state(const AVD_AVND 
+*node);
 #endif
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
@@ -41,6 +41,7 @@
 #include <amf_defs.h>
 #include <amf_d2nmsg.h>
 #include "db_template.h"
+#include "node.h"
 
 class AVD_SU;
 class AVD_SI;
@@ -382,7 +383,28 @@ public:
        virtual uint32_t susi_failed(AVD_CL_CB *cb, AVD_SU *su,
                struct avd_su_si_rel_tag *susi, AVSV_SUSI_ACT act,
                SaAmfHAStateT state) = 0;
-
+       /**
+         * Handle NG admin operation lock and shutdown.
+         * Default implementation in base class (not pure virtual)
+         * @param su
+         * @param ng 
+         * @return
+         */
+       virtual void ng_admin(AVD_SU *su, AVD_AMF_NG *ng);
+        /**
+         * Checks if SG has assignments only on the nodes of nodegroup. 
+         * @param ng
+         * @return
+         */
+       bool is_sg_assigned_only_in_ng(const AVD_AMF_NG *ng);
+       /**
+         * Does an instantiable or an inservice SU exist outside the nodegroup.
+         * @param ng
+         * @return
+         */
+       bool is_sg_serviceable_outside_ng(const AVD_AMF_NG *ng);
+       SaAisErrorT check_sg_stability();
+       bool ng_using_saAmfSGAdminState;
 private:
        // disallow copy and assign, TODO(hafe) add common macro for this
        AVD_SG(const AVD_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
@@ -134,6 +134,9 @@ 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();
+       SaAisErrorT check_su_stability();
  private:
        void initialize();
        void send_attribute_update(AVSV_AMF_SU_ATTR_ID attrib_id); 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
@@ -126,6 +126,7 @@ static void node_add_to_model(AVD_AVND *
        }
 
        node->cluster = avd_cluster;
+       node->admin_ng = NULL;
 
        avd_node_db_add(node);
        m_AVSV_SEND_CKPT_UPDT_ASYNC_ADD(avd_cb, node, 
AVSV_CKPT_AVD_NODE_CONFIG); @@ -1373,6 +1374,22 @@ void 
node_reset_su_try_inst_counter(cons
                su = su->avnd_list_su_next;
        }
 }
+/**
+ * @brief  Checks all  nodegroup of nodes are in UNLOCKED state.
+ * @param  ptr to Node (AVD_AVND).
+ * @return true/false
+ */
+bool are_all_ngs_in_unlocked_state(const AVD_AVND *node) {
+        for (std::map<std::string, AVD_AMF_NG*>::const_iterator it = 
nodegroup_db->begin();
+                        it != nodegroup_db->end(); it++) {
+                AVD_AMF_NG *ng = it->second;
+                if ((node_in_nodegroup(Amf::to_string(&node->name), ng) == 
true) &&
+                                (ng->saAmfNGAdminState != 
SA_AMF_ADMIN_UNLOCKED))
+                        return false;
+        }
+        return true;
+}
 
 void avd_node_constructor(void)
 {
diff --git a/osaf/services/saf/amf/amfd/nodegroup.cc 
b/osaf/services/saf/amf/amfd/nodegroup.cc
--- a/osaf/services/saf/amf/amfd/nodegroup.cc
+++ b/osaf/services/saf/amf/amfd/nodegroup.cc
@@ -124,14 +124,18 @@ static AVD_AMF_NG *ng_create(SaNameT *dn
                LOG_ER("Node groups must contian at least one node");
                goto done;
        }
-
+       if (immutil_getAttr(const_cast<SaImmAttrNameT>("saAmfNGAdminState"),
+                               attributes, 0, &ng->saAmfNGAdminState) != 
SA_AIS_OK) {
+                ng->saAmfNGAdminState = SA_AMF_ADMIN_UNLOCKED;
+               LOG_NO("Setting saAmfNGAdminState to 
:'%u'",ng->saAmfNGAdminState);
+       }
+       //TODO_NG: Add protection against shutting down state and lock-in state.
        rc = 0;
 done:
        if (rc != 0) {
                delete ng;
                ng = NULL;
        }
-
        return ng;
 }
 
@@ -393,7 +397,12 @@ static SaAisErrorT ng_ccb_completed_dele
 
        TRACE_ENTER2("%u", ng->number_nodes());
        std::set<std::string>::const_iterator iter;
-
+       if ((ng->saAmfNGAdminState != SA_AMF_ADMIN_LOCKED) &&
+                       (ng->saAmfNGAdminState != SA_AMF_ADMIN_UNLOCKED)) {
+               report_ccb_validation_error(opdata, "'%s' can be deleted in 
locked or unlocked admin state",
+                                       ng->name.value);
+               goto done;
+       }
        for (iter = ng->saAmfNGNodeList.begin();
                iter != ng->saAmfNGNodeList.end();
                ++iter) {
@@ -538,12 +547,409 @@ static void ng_ccb_apply_cb(CcbUtilOpera  }
 
 /**
+ * @brief  sets admin state of ng. Update in IMM, saflogging and notification 
for it.
+ * @param  ptr to Nodegroup (AVD_AMF_NG).
+ * @param  state(SaAmfAdminStateT).
+ */
+void avd_ng_admin_state_set(AVD_AMF_NG* ng, SaAmfAdminStateT state) {
+       SaAmfAdminStateT old_state = ng->saAmfNGAdminState;
+       
+       osafassert(state <= SA_AMF_ADMIN_SHUTTING_DOWN);
+       TRACE_ENTER2("%s AdmState %s => %s", ng->name.value,
+                       avd_adm_state_name[old_state], 
avd_adm_state_name[state]);
+       saflog(LOG_NOTICE, amfSvcUsrName, "%s AdmState %s => %s", 
ng->name.value,
+                  avd_adm_state_name[old_state], avd_adm_state_name[state]);   
   
+       ng->saAmfNGAdminState = state;
+       avd_saImmOiRtObjectUpdate(&ng->name,
+                       const_cast<SaImmAttrNameT>("saAmfNGAdminState"), 
+                       SA_IMM_ATTR_SAUINT32T, &ng->saAmfNGAdminState); }
+/**
+ * @brief  Verify if Node is stable for admin operation on Nodegroup etc.
+ * @param  ptr to node(AVD_AVND).
+ * @param  ptr to nodegroup(AVD_AMF_NG).
+ * @Return SA_AIS_OK/SA_AIS_ERR_TRY_AGAIN/SA_AIS_ERR_BAD_OPERATION.
+*/
+static SaAisErrorT check_node_stability(const AVD_AVND *node, const 
+AVD_AMF_NG *ng) {
+       SaAisErrorT rc = SA_AIS_OK;
+
+       if (node->admin_node_pend_cbk.admin_oper != 0) {
+               LOG_NO("'%s' undergoing admin operation", node->name.value);
+               rc = SA_AIS_ERR_TRY_AGAIN;
+               goto done;
+       }
+       if (node->clm_pend_inv != 0) {
+               LOG_NO("'%s' Clm operation going on", node->name.value);
+               rc = SA_AIS_ERR_TRY_AGAIN;
+                goto done;
+        }
+       for (AVD_SU *su = node->list_of_su; su != NULL;  
+                       su = su->avnd_list_su_next) {
+               rc = su->sg_of_su->check_sg_stability();        
+               if (rc != SA_AIS_OK)
+                       goto done;
+               rc = su->check_su_stability();
+               if (rc != SA_AIS_OK)
+                       goto done;
+       }
+done:
+       return rc;
+}
+/**
+ * @brief  Ccheck for unsupported red model and warning for service outage in 
any SG.
+ * @param  ptr to node(AVD_AVND).
+ * @param  ptr to nodegroup(AVD_AMF_NG).
+ * @Return SA_AIS_OK/SA_AIS_ERR_BAD_OPERATION.
+*/
+static SaAisErrorT check_red_model_service_outage(const AVD_AMF_NG *ng) 
+{
+       SaAisErrorT rc = SA_AIS_OK;
+       std::set<std::string> tmp_sg_list;
+       for (std::set<std::string>::const_iterator iter = 
ng->saAmfNGNodeList.begin();
+                       iter != ng->saAmfNGNodeList.end(); ++iter) {
+               AVD_AVND *node = avd_node_get(*iter);
+               for (AVD_SU *su = node->list_of_su; su != NULL;  
+                               su = su->avnd_list_su_next) {
+                       //Make a temorary list_of_SG for later verification of 
service outage.
+                       tmp_sg_list.insert(Amf::to_string(&su->sg_of_su->name));
+               }
+       }
+       for (std::set<std::string>::const_iterator iter =  tmp_sg_list.begin();
+                                iter != tmp_sg_list.end(); ++iter) {
+               AVD_SG *sg = sg_db->find(*iter);
+               /*
+                  To avoid service outage of complete SG check if there exists 
atleast
+                  one instantiable or atleast one in service SU outside the 
nodegroup.
+                */
+               //As of now, AMF will throw only warning, but operation will 
continue.  
+               if (sg->is_sg_serviceable_outside_ng(ng) == true)
+                       LOG_NO("service outage for '%s' because of 
shutdown/lock "
+                                       "on 
'%s'",sg->name.value,ng->name.value);
+
+               if ((sg->sg_redundancy_model == SA_AMF_N_WAY_REDUNDANCY_MODEL) 
||
+                               (sg->sg_redundancy_model == 
SA_AMF_NPM_REDUNDANCY_MODEL)) { 
+                       LOG_NO("Admin op on '%s'  hosting SUs of '%s' with 
redundancy '%u' "
+                                       "is not supported",ng->name.value, 
sg->name.value,
+                                       sg->sg_redundancy_model);
+                       rc = SA_AIS_ERR_NOT_SUPPORTED;
+                       tmp_sg_list.clear();
+                       goto done;
+               }
+       }
+       tmp_sg_list.clear();
+done:
+       return rc;
+}
+/**
+ * @brief  Verify if all the AMF entities are stable in NodeGroup.
+ *         If all the entities are stable then AMF can accept
+ *         admin operation on nodegroup.
+ * @param  ptr to nodegroup(AVD_AMF_NG).
+ * @Return SA_AIS_OK/SA_AIS_ERR_TRY_AGAIN/SA_AIS_ERR_BAD_OPERATION.
+*/
+static SaAisErrorT check_ng_stability(const AVD_AMF_NG *ng) {
+       SaAisErrorT rc = SA_AIS_OK;
+               
+       if (ng->admin_ng_pend_cbk.admin_oper != 0) {
+               LOG_NO("'%s' is already undergoing admin operation", 
ng->name.value);
+               rc = SA_AIS_ERR_TRY_AGAIN;
+               goto done;
+       }
+       //Check for other AMF entities which are part of nodegroup.     
+       for (std::set<std::string>::const_iterator iter = 
ng->saAmfNGNodeList.begin();
+                                iter != ng->saAmfNGNodeList.end(); ++iter) {
+                        AVD_AVND *node = avd_node_get(*iter);
+                       rc = check_node_stability(node, ng);
+                       if (rc != SA_AIS_OK)
+                               goto done;
+       }
+done:
+       return rc;
+}
+/**
+ * @brief       This function completes admin operation on Nodegroup.
+ *              It responds IMM with the result of admin operation on 
Nodegroup.
+ *              It also unsets all the admin op related parameters.
+ * @param       ptr to Nodegroup (AVD_AMF_NG). 
+ */
+void ng_complete_admin_op(AVD_AMF_NG *ng, SaAisErrorT result) {
+       if (ng->admin_ng_pend_cbk.invocation != 0) {
+               TRACE("Replying to IMM for admin op on '%s'", ng->name.value);
+               avd_saImmOiAdminOperationResult(avd_cb->immOiHandle,
+                               ng->admin_ng_pend_cbk.invocation, result);
+               ng->admin_ng_pend_cbk.invocation = 0;
+               ng->admin_ng_pend_cbk.admin_oper = 
static_cast<SaAmfAdminOperationIdT>(0);
+       }
+       for (std::set<std::string>::const_iterator iter = 
ng->saAmfNGNodeList.begin();
+                       iter != ng->saAmfNGNodeList.end(); ++iter) {
+               AVD_AVND *node = avd_node_get(*iter);
+               node->admin_ng = NULL;
+       }
+}
+/**
+ * @brief       Handles node level funtionality during nodegroup lock
+ *              or shutdown operation. For each SU hosted on this node, 
+ *              it calls redundancy model specific handler (sg->ng_admin()),
+ *              defined in the sg_*_fsm.cc, to handle assignments at SU level. 
+ *              Also it updates ng->node_oper_list for tracking operation on 
+ *              this node.
+ * @param       ptr to Node (AVD_AVND).
+ */
+void ng_node_lock_and_shutdown(AVD_AVND *node) {
+       TRACE_ENTER2("'%s'",node->name.value);
+       if (node->node_info.member == false) {
+               node_admin_state_set(node, SA_AMF_ADMIN_LOCKED);
+               LOG_NO("%s' LOCK: CLM node is not member", node->name.value);
+               return;
+       }
+       if (avd_cb->init_state == AVD_INIT_DONE) {
+               node_admin_state_set(node, SA_AMF_ADMIN_LOCKED);
+               for(AVD_SU *su = node->list_of_su; su != NULL; su = 
su->avnd_list_su_next) {
+                       
su->set_readiness_state(SA_AMF_READINESS_OUT_OF_SERVICE);
+               }
+               return;
+       }
+       if (node->saAmfNodeOperState == SA_AMF_OPERATIONAL_DISABLED)
+               return;
+       for (AVD_SU *su = node->list_of_su; su != NULL;  su = 
su->avnd_list_su_next) {
+               su->set_readiness_state(SA_AMF_READINESS_OUT_OF_SERVICE);
+               su->sg_of_su->ng_admin(su, node->admin_ng);
+       }
+       if (node->su_cnt_admin_oper > 0)
+               
node->admin_ng->node_oper_list.insert(Amf::to_string(&node->name));
+       TRACE_LEAVE2("node_oper_list 
+size:%u",node->admin_ng->oper_list_size());
+}
+/*
+ * @brief       Handles unlock of nodegroup. For each SU hosted on this node,
+ *              it calls redundancy model specific assignment handler i.e 
+ *             (sg->su_insvc()), defined in the sg_*_fsm.cc, to assign SUs 
+ *              based on ranks. Also SG of each SU is looked for instantiation 
of 
+ *             new SUs. Also it updates ng->node_oper_list for tracking 
operation
+ *             on this node.
+ * @param       ptr to Nodegroup (AVD_AMF_NG).
+ */
+void ng_unlock(AVD_AMF_NG *ng)
+{
+       TRACE_ENTER2("'%s'",ng->name.value);
+       for (std::set<std::string>::const_iterator iter = 
ng->saAmfNGNodeList.begin();
+                       iter != ng->saAmfNGNodeList.end(); ++iter) {
+               AVD_AVND *node = avd_node_get(*iter);
+               node_admin_state_set(node, SA_AMF_ADMIN_UNLOCKED);
+               if (node->node_info.member == false) {
+                       LOG_NO("'%s' UNLOCK: CLM node is not member", 
node->name.value);
+                       continue;
+               }
+               node->su_cnt_admin_oper = 0;
+               node->admin_ng = ng;
+       }
+       for (std::set<std::string>::const_iterator iter = 
ng->saAmfNGNodeList.begin();
+                       iter != ng->saAmfNGNodeList.end(); ++iter) {
+               AVD_AVND *node = avd_node_get(*iter);
+               if ((node->saAmfNodeOperState == SA_AMF_OPERATIONAL_DISABLED) ||
+                               (node->node_info.member == false))
+                       continue;
+               for (AVD_SU *su = node->list_of_su; su != NULL;  su = 
su->avnd_list_su_next) {
+                       if (su->is_in_service() == true) {
+                               
su->set_readiness_state(SA_AMF_READINESS_IN_SERVICE);
+                       }
+               }
+       }
+       for (std::set<std::string>::const_iterator iter = 
ng->saAmfNGNodeList.begin();
+                       iter != ng->saAmfNGNodeList.end(); ++iter) {
+               AVD_AVND *node = avd_node_get(*iter);
+               if ((node->saAmfNodeOperState == SA_AMF_OPERATIONAL_DISABLED) ||
+                               (node->node_info.member == false) ||
+                               (avd_cb->init_state == AVD_INIT_DONE))
+                       continue;
+               /*
+                  By this time Nodes of node group are in unlocked state.Let 
the
+                  SG semantics decide which su to chose for assignment and 
instantiation. 
+                */
+               for (AVD_SU *su = node->list_of_su; su != NULL;  su = 
su->avnd_list_su_next) {
+                       su->sg_of_su->su_insvc(avd_cb, su);
+                       avd_sg_app_su_inst_func(avd_cb, su->sg_of_su);
+               }
+               if (node->su_cnt_admin_oper > 0)
+                       
node->admin_ng->node_oper_list.insert(Amf::to_string(&node->name));
+       }
+       TRACE_LEAVE2("node_oper_list size:%u",ng->oper_list_size()); }
+/**
+ * Handle admin operations on SaAmfNodeGroup objects.
+ *
+ * @param immoi_handle
+ * @param invocation
+ * @param ng_name
+ * @param op_id
+ * @param params
+ */
+static void ng_admin_op_cb(SaImmOiHandleT immoi_handle, SaInvocationT 
invocation,
+               const SaNameT *ng_name, SaImmAdminOperationIdT op_id,
+               const SaImmAdminOperationParamsT_2 **params) {
+       SaAisErrorT rc = SA_AIS_OK;
+       AVD_AMF_NG *ng = avd_ng_get(ng_name);   
+       TRACE_ENTER2("'%s', inv:'%llu', 
+op:'%llu'",ng_name->value,invocation,op_id);
+
+       switch(op_id) {
+       case SA_AMF_ADMIN_LOCK:
+               rc = check_ng_stability(ng);    
+               if (rc != SA_AIS_OK) {
+                       report_admin_op_error(avd_cb->immOiHandle, invocation, 
+                                       SA_AIS_ERR_TRY_AGAIN, NULL,
+                                       "Some entity is unstable, Operation 
cannot "
+                                       "be performed on '%s'"
+                                       "Check syslog for entity details", 
ng_name->value);
+                       goto done;
+               }
+               if (ng->saAmfNGAdminState == SA_AMF_ADMIN_LOCKED) {
+                        report_admin_op_error(avd_cb->immOiHandle, invocation, 
SA_AIS_ERR_NO_OP, NULL,
+                                        "'%s' Already in LOCKED state", 
ng->name.value);
+                        goto done;
+                }
+               if (ng->saAmfNGAdminState == SA_AMF_ADMIN_LOCKED_INSTANTIATION) 
{
+                       report_admin_op_error(avd_cb->immOiHandle, invocation, 
SA_AIS_ERR_BAD_OPERATION, NULL,
+                                       "'%s' Invalid Admin Operation LOCK in 
state %s",
+                                       ng->name.value, 
avd_adm_state_name[ng->saAmfNGAdminState]);
+                       goto done;
+               }
+               rc = check_red_model_service_outage(ng);
+               if (rc != SA_AIS_OK) {
+                       report_admin_op_error(avd_cb->immOiHandle, invocation, 
+                                       SA_AIS_ERR_NOT_SUPPORTED, NULL,
+                                       "SUs of unsupported red models hosted 
on '%s'"
+                                       "Check syslog for entity details", 
ng_name->value);
+                       goto done;
+               }
+               ng->admin_ng_pend_cbk.invocation = invocation;
+               ng->admin_ng_pend_cbk.admin_oper = 
static_cast<SaAmfAdminOperationIdT>(op_id);
+               ng->node_oper_list.clear();
+
+               avd_ng_admin_state_set(ng, SA_AMF_ADMIN_LOCKED);
+               for (std::set<std::string>::const_iterator iter = 
ng->saAmfNGNodeList.begin();
+                               iter != ng->saAmfNGNodeList.end(); ++iter) {
+                       AVD_AVND *node = avd_node_get(*iter);
+                       node->su_cnt_admin_oper = 0;
+                       node->admin_ng = ng;
+                       node_admin_state_set(node, SA_AMF_ADMIN_LOCKED);
+               }
+               for (std::set<std::string>::const_iterator iter = 
ng->saAmfNGNodeList.begin();
+                               iter != ng->saAmfNGNodeList.end(); ++iter) {
+                       AVD_AVND *node = avd_node_get(*iter);
+                       ng_node_lock_and_shutdown(node);
+               }
+               if (ng->node_oper_list.empty())
+                       ng_complete_admin_op(ng, SA_AIS_OK);
+               break;
+       case SA_AMF_ADMIN_SHUTDOWN:
+               rc = check_ng_stability(ng);    
+               if (rc != SA_AIS_OK) {
+                       report_admin_op_error(avd_cb->immOiHandle, invocation, 
+                                       SA_AIS_ERR_TRY_AGAIN, NULL,
+                                       "Some entity is unstable, Operation 
cannot "
+                                       "be performed on '%s'"
+                                       "Check syslog for entity details", 
ng_name->value);
+                       goto done;
+               }
+               if (ng->saAmfNGAdminState == SA_AMF_ADMIN_SHUTTING_DOWN) {
+                       report_admin_op_error(avd_cb->immOiHandle, invocation, 
SA_AIS_ERR_NO_OP, NULL,
+                                       "'%s' Already in SHUTTING DOWN state", 
ng->name.value);
+                       goto done;
+               }
+               if (ng->saAmfNGAdminState != SA_AMF_ADMIN_UNLOCKED) {
+                       report_admin_op_error(avd_cb->immOiHandle, invocation, 
SA_AIS_ERR_BAD_OPERATION, NULL,
+                                       "'%s' Invalid Admin Operation SHUTDOWN 
in state %s",
+                                       ng->name.value, 
avd_adm_state_name[ng->saAmfNGAdminState]);
+                       goto done;
+               }
+               rc = check_red_model_service_outage(ng);
+               if (rc != SA_AIS_OK) {
+                       report_admin_op_error(avd_cb->immOiHandle, invocation, 
+                                       SA_AIS_ERR_NOT_SUPPORTED, NULL,
+                                       "SUs of unsupported red models hosted 
on '%s'"
+                                       "Check syslog for entity details", 
ng_name->value);
+                       goto done;
+               }
+               ng->admin_ng_pend_cbk.invocation = invocation;
+               ng->admin_ng_pend_cbk.admin_oper = 
static_cast<SaAmfAdminOperationIdT>(op_id);
+               ng->node_oper_list.clear();
+
+               avd_ng_admin_state_set(ng, SA_AMF_ADMIN_SHUTTING_DOWN);
+               for (std::set<std::string>::const_iterator iter = 
ng->saAmfNGNodeList.begin();
+                               iter != ng->saAmfNGNodeList.end(); ++iter) {
+                       AVD_AVND *node = avd_node_get(*iter);
+                       node->su_cnt_admin_oper = 0;
+                       node->admin_ng = ng;
+                       node_admin_state_set(node, SA_AMF_ADMIN_SHUTTING_DOWN);
+               }
+               for (std::set<std::string>::const_iterator iter = 
ng->saAmfNGNodeList.begin();
+                               iter != ng->saAmfNGNodeList.end(); ++iter) {
+                       AVD_AVND *node = avd_node_get(*iter);
+                       ng_node_lock_and_shutdown(node);
+                       if (node->su_cnt_admin_oper == 0)
+                               node_admin_state_set(node, SA_AMF_ADMIN_LOCKED);
+               }
+               if (ng->node_oper_list.empty())  {
+                       avd_ng_admin_state_set(ng, SA_AMF_ADMIN_LOCKED);
+                       for (std::set<std::string>::const_iterator iter = 
ng->saAmfNGNodeList.begin();
+                                       iter != ng->saAmfNGNodeList.end(); 
++iter) {
+                               AVD_AVND *node = avd_node_get(*iter);
+                               node_admin_state_set(node, SA_AMF_ADMIN_LOCKED);
+                       }
+                       ng_complete_admin_op(ng, SA_AIS_OK);
+               }
+               break;
+       case SA_AMF_ADMIN_UNLOCK:
+               rc = check_ng_stability(ng);
+               if (rc != SA_AIS_OK) {
+                       report_admin_op_error(avd_cb->immOiHandle, invocation,
+                                       SA_AIS_ERR_TRY_AGAIN, NULL,
+                                       "Some entity is unstable, Operation 
cannot "
+                                       "be performed on '%s'"
+                                       "Check syslog for entity details", 
ng_name->value);
+                       goto done;
+               }
+               if (ng->saAmfNGAdminState == SA_AMF_ADMIN_UNLOCKED) {
+                       report_admin_op_error(avd_cb->immOiHandle, invocation, 
SA_AIS_ERR_NO_OP, NULL,
+                                       "'%s' Already in UNLOCKED state", 
ng->name.value);
+                        goto done;
+               }
+               if (ng->saAmfNGAdminState != SA_AMF_ADMIN_LOCKED) {
+                       report_admin_op_error(avd_cb->immOiHandle, invocation, 
SA_AIS_ERR_BAD_OPERATION, NULL,
+                                       "'%s' Invalid Admin Operation UNLOCK in 
state %s",
+                                        ng->name.value, 
avd_adm_state_name[ng->saAmfNGAdminState]);
+                        goto done;
+                }
+               ng->admin_ng_pend_cbk.invocation = invocation;
+               ng->admin_ng_pend_cbk.admin_oper = 
static_cast<SaAmfAdminOperationIdT>(op_id);
+               ng->node_oper_list.clear();
+
+               avd_ng_admin_state_set(ng, SA_AMF_ADMIN_UNLOCKED);
+               ng_unlock(ng);
+               if (ng->node_oper_list.empty())
+                       ng_complete_admin_op(ng, SA_AIS_OK);
+               break;
+       default:
+               report_admin_op_error(avd_cb->immOiHandle, invocation, 
SA_AIS_ERR_NOT_SUPPORTED, NULL,
+                               "Operation is not supported (%llu)", op_id);
+               break;
+       }
+done:
+       TRACE_LEAVE();
+}
+
+/**
  * Constructor for node group class. Should be called first of all.
  */
 void avd_ng_constructor(void)
 {
        nodegroup_db = new AmfDb<std::string, AVD_AMF_NG>;
-       avd_class_impl_set("SaAmfNodeGroup", NULL, NULL, ng_ccb_completed_cb,
+       avd_class_impl_set("SaAmfNodeGroup", NULL, ng_admin_op_cb, 
+ng_ccb_completed_cb,
                        ng_ccb_apply_cb);
 }
 
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
@@ -567,7 +567,6 @@ void avd_mds_qsd_role_evh(AVD_CL_CB *cb,
        uint32_t rc = NCSCC_RC_SUCCESS;
 
        TRACE_ENTER();
-
        /* Only accept this event in controller switch-over state, in other
         * states it is invalid and indicates severe cluster problems.
         */
@@ -612,7 +611,21 @@ void avd_mds_qsd_role_evh(AVD_CL_CB *cb,
                cb->swap_switch = false;
                amfd_switch_qsd_actv(cb);
        }
-
+       /*Since this AMFD has given up implementor role, clear admin operation 
params  
+          for admin operation on nodegroup*/
+       for (std::map<std::string, AVD_AMF_NG*>::const_iterator it = 
nodegroup_db->begin();
+                       it != nodegroup_db->end(); it++) {
+               AVD_AMF_NG *ng = it->second;
+               if (ng->admin_ng_pend_cbk.invocation != 0) {
+                       ng->admin_ng_pend_cbk.invocation = 0;
+                       ng->admin_ng_pend_cbk.admin_oper = 
static_cast<SaAmfAdminOperationIdT>(0);
+                       for (std::set<std::string>::const_iterator iter = 
ng->saAmfNGNodeList.begin();
+                                       iter != ng->saAmfNGNodeList.end(); 
++iter) {
+                               AVD_AVND *node = avd_node_get(*iter);
+                               node->admin_ng = NULL;
+                       }
+               }
+       }
        TRACE_LEAVE();
 }
 
diff --git a/osaf/services/saf/amf/amfd/sg.cc b/osaf/services/saf/amf/amfd/sg.cc
--- a/osaf/services/saf/amf/amfd/sg.cc
+++ b/osaf/services/saf/amf/amfd/sg.cc
@@ -136,6 +136,7 @@ AVD_SG::AVD_SG():
        su_oper_list.su = NULL;
        su_oper_list.next = NULL;
        adminOp_invocationId = 0;
+       ng_using_saAmfSGAdminState = false;
 }
 
 static AVD_SG *sg_new(const SaNameT *dn, SaAmfRedundancyModelT 
redundancy_model) @@ -1801,6 +1802,10 @@ SaAisErrorT AVD_SG::si_swap(AVD_SI 
*si, 
        return SA_AIS_ERR_NOT_SUPPORTED;
 }
 
+// default implementation
+void AVD_SG::ng_admin(AVD_SU* su, AVD_AMF_NG* ng) {
+       return;
+}
 /**
  * @brief  Checks if SG is stable with respect to lock-in or unlock-on 
operation.  
  *
@@ -1875,3 +1880,80 @@ bool sg_stable_after_lock_in_or_unlock_i
                
        return true;
 }
+/*
+ * @brief      Checks if SG has assignments only in the nodes of nodegroup.
+ * @param[in]  ptr to Nodegroup (AVD_AMF_NG).   
+ * @return     true/false.
+ */
+bool AVD_SG::is_sg_assigned_only_in_ng(const AVD_AMF_NG *ng) {
+       for (AVD_SU *su = list_of_su; su; su = su->sg_list_su_next) {
+               if (su->list_of_susi == NULL)
+                       continue;
+               //Return if this assigned su is not in this ng.
+               if (node_in_nodegroup(Amf::to_string(&su->su_on_node->name), 
ng) == false)
+                       return false;
+       }
+       return true;
+}
+/*
+ * @brief      Checks if there exists atleast one instantiable or inservice
+ *             SU outside the nodegroup. 
+ * @param[in]  ptr to Nodegroup (AVD_AMF_NG).
+ * @return     true/false.
+ */
+bool AVD_SG::is_sg_serviceable_outside_ng(const AVD_AMF_NG *ng) {
+       for (AVD_SU *su = list_of_su; su; su = su->sg_list_su_next) {
+               //Check if any su exists outside nodegroup for this sg. 
+               if (node_in_nodegroup(Amf::to_string(&su->su_on_node->name), 
ng) == false) {
+                       /* 
+                          During lock or shutdown operation on Node or SU, AMF
+                          instantiates new SUs or it will switch-over existing 
+                          assignments of locked Node or SU to other SUs.
+                          To avoid service outage of complete SG check if 
+                          there exists atleast one instantiable or atleast one 
+                          in service SU outside the nodegroup.
+                        */
+                       //TODO_NG:Evaluate if more parameters can be checked.
+                       if ((su->is_instantiable() == true) || 
+                                        (su->is_in_service() == true))
+                               return false;
+               }
+       }
+       return true;
+}
+/**
+ * @brief  Verify if SG is stable for admin operation on entity 
+           Node, App and Nodegroup etc.
+ * @param  ptr to SG(AVD_SG).
+ * @Return SA_AIS_OK/SA_AIS_ERR_TRY_AGAIN/SA_AIS_ERR_BAD_OPERATION.
+*/
+SaAisErrorT AVD_SG::check_sg_stability() {
+       SaAisErrorT rc = SA_AIS_OK;
+       if (sg_fsm_state != AVD_SG_FSM_STABLE) {
+               LOG_NO("'%s' is in unstable/transition state", name.value);
+               rc = SA_AIS_ERR_TRY_AGAIN;
+               goto done;
+       }
+       if ((adminOp_invocationId != 0) || (adminOp != 0))  {
+               LOG_NO("Admin operation is already going on '%s' ", name.value);
+               rc = SA_AIS_ERR_TRY_AGAIN;
+               goto done;
+        }
+       if (sg_is_tolerance_timer_running_for_any_si(this)) {
+               LOG_NO("Tolerance timer is running for some of the SI's in the 
SG '%s',"
+                               " so differing admin opr", name.value);
+               rc = SA_AIS_ERR_TRY_AGAIN;
+                goto done;
+        }
+       if (csi_assignment_validate(this) == true) {
+                LOG_NO("Single Csi assignment undergoing in '%s'", name.value);
+               rc = SA_AIS_ERR_TRY_AGAIN;
+                goto done;
+        }
+done:
+       return rc;
+
+}
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
@@ -199,9 +199,16 @@ npisu_done:
 
        if (false == ckpt) {
                if (avd_snd_susi_msg(cb, su, susi, AVSV_SUSI_ACT_ASGN, false, 
NULL) == NCSCC_RC_SUCCESS) {
-                       if (su->su_on_node->admin_node_pend_cbk.invocation != 
0) {
-                               su->su_on_node->su_cnt_admin_oper++;
-                               TRACE("su_cnt_admin_oper:%u", 
su->su_on_node->su_cnt_admin_oper);
+                       AVD_AVND *node = su->su_on_node;
+                       if ((node->admin_node_pend_cbk.invocation != 0) || 
((node->admin_ng != NULL) &&
+                                               
(node->admin_ng->admin_ng_pend_cbk.invocation !=0))) {
+                               node->su_cnt_admin_oper++;
+                               TRACE("node:'%s', su_cnt_admin_oper:%u", 
+                                               node->name.value, 
node->su_cnt_admin_oper);
+                               if (node->admin_ng != NULL) {
+                                       
node->admin_ng->node_oper_list.insert(Amf::to_string(&node->name));
+                                       TRACE("node_oper_list 
size:%u",node->admin_ng->oper_list_size());
+                               }
                        }
                } else {
                        /* free all the CSI assignments and end this loop */
@@ -269,7 +276,78 @@ static void node_complete_admin_op(AVD_A
                node->admin_node_pend_cbk.admin_oper = 
static_cast<SaAmfAdminOperationIdT>(0);
        }
 }
-
+/**
+ * @brief       When AMFD gets assignment response message or escalation
+ *              request from AMFND, it runs SG FSM. In the context of admin
+ *              operation on any AMF entity, after running SG FSM, AMFD 
+ *              evaluates if this message or request marks the completion 
+ *              of admin operation or atleast makes some progress in admin 
+ *              operation. This functions evaluates the message or request 
+ *              for nodegroup admin operation.
+ * @param[in]   ptr to SU (AVD_SU). 
+ * @param[in]   res(SaAisErrorT). 
+ */
+static void process_su_si_response_for_ng(AVD_SU *su, SaAisErrorT res)
+{
+       TRACE_ENTER2("'%s'",su->name.value);
+       AVD_AMF_NG *ng = su->su_on_node->admin_ng;
+       AVD_AVND *node = su->su_on_node;
+       bool flag = false;
+       /* Node may be in SHUTTING_DOWN state because of shutdown operation
+          on nodegroup. Check if node can be transitioned to LOCKED sate.*/ 
+       if (node->saAmfNodeAdminState == SA_AMF_ADMIN_SHUTTING_DOWN) {
+               m_AVD_IS_NODE_LOCK(node, flag);
+               if (flag == true)
+                       node_admin_state_set(node, SA_AMF_ADMIN_LOCKED);
+       }
+       /*In 2N model, if both active or standby SUs were part of nodegroup then
+         AMFD internally executes operation as equivalent to SG shutdown/lock.
+         So after completion of operation, clear SG admin state and give fresh
+         assignments outside the nodegroup.*/
+       if ((su->sg_of_su->ng_using_saAmfSGAdminState == true) &&
+                       (su->sg_of_su->saAmfSGAdminState == 
SA_AMF_ADMIN_LOCKED) &&
+                       (su->sg_of_su->sg_fsm_state == AVD_SG_FSM_STABLE)) {
+               su->sg_of_su->saAmfSGAdminState = SA_AMF_ADMIN_UNLOCKED;
+               m_AVSV_SEND_CKPT_UPDT_ASYNC_UPDT(avd_cb, su->sg_of_su, 
AVSV_CKPT_SG_ADMIN_STATE);
+               su->sg_of_su->ng_using_saAmfSGAdminState = false;
+               
TRACE("ng_using_saAmfSGAdminState:%u",su->sg_of_su->ng_using_saAmfSGAdminState);
+               su->sg_of_su->realign(avd_cb, su->sg_of_su);
+               if (su->sg_of_su->sg_fsm_state == AVD_SG_FSM_STABLE) {
+                       /*This means no new assignments in the SG.*/
+                       avd_sidep_sg_take_action(su->sg_of_su);
+                       avd_sg_app_su_inst_func(avd_cb, su->sg_of_su);
+               }
+       }
+       if (ng == NULL)
+               goto done;
+       /* During nodegroup shutdown operation, mark nodegrouoop LOCKED if 
+          all nodes transtioned to LOCKED state.*/
+       if (ng->saAmfNGAdminState == SA_AMF_ADMIN_SHUTTING_DOWN) {
+               flag = true;            
+               for (std::set<std::string>::const_iterator iter = 
ng->saAmfNGNodeList.begin();
+                               iter != ng->saAmfNGNodeList.end(); ++iter) {
+                       AVD_AVND *tmp_node = avd_node_get(*iter);
+                       if (tmp_node->saAmfNodeAdminState != 
SA_AMF_ADMIN_LOCKED)
+                               flag = false;
+               }
+               if (flag == true) {
+                       TRACE("Move '%s' to locked state as all nodes are 
locked.", ng->name.value);
+                       avd_ng_admin_state_set(ng, SA_AMF_ADMIN_LOCKED);
+               }
+       }
+       /*If no futher SU is undergoing assignment changes, erase node from
+          nodgroup operation tracking list.*/
+       if (node->su_cnt_admin_oper == 0) {
+               ng->node_oper_list.erase(Amf::to_string(&node->name));
+               TRACE("node_oper_list size:%u",ng->oper_list_size());
+       }
+       /*If assignment changes are done on all the SUs on each node of 
nodegroup
+         then reply to IMM for status of admin operation.*/
+       if (ng->node_oper_list.empty())
+               ng_complete_admin_op(ng, res);
+done:
+       TRACE_LEAVE();
+}
 /**
  * @brief      Perform failover of SU as a single entity and free all SUSIs 
associated with this SU.
  * @param      su 
@@ -295,8 +373,9 @@ static uint32_t sg_su_failover_func(AVD_
        else
                su->complete_admin_op(SA_AIS_ERR_TIMEOUT);
        su->disable_comps(SA_AIS_ERR_TIMEOUT);
-       if (su->su_on_node->admin_node_pend_cbk.invocation != 0) {
-               /* Node level operation is going on the node hosting the SU for 
which 
+       if ((su->su_on_node->admin_node_pend_cbk.invocation != 0) ||
+                       (su->su_on_node->admin_ng != NULL)) {
+               /* Node or nodegroup level operation is going on the node 
hosting the SU for which 
                   sufailover got escalated. Sufailover event will always come 
after the 
                   initiation of node level operation on the list of SUs. So if 
this SU has 
                   list of SUSIs, AMF would have sent assignment as a part of 
node level operation.
@@ -316,8 +395,13 @@ static uint32_t sg_su_failover_func(AVD_
                        su->su_on_node->su_cnt_admin_oper--;
 
                /* If node level operation is finished on all the SUs, reply to 
imm.*/
-               if (su->su_on_node->su_cnt_admin_oper == 0)
-                       node_complete_admin_op(su->su_on_node, res);
+               if (su->su_on_node->su_cnt_admin_oper == 0) {
+                       AVD_AVND *node = su->su_on_node;
+                       node_complete_admin_op(node, res);
+               }
+
+               /* If nodegroup level operation is finished on all the nodes, 
reply to imm.*/
+               process_su_si_response_for_ng(su, res);
        }
 
        /*If the AvD is in AVD_APP_STATE then reassign all the SUSI assignments 
for this SU */
@@ -729,6 +813,7 @@ static void susi_assign_msg_dump(const c
        LOG_ER("%s:%d %s", func, line, info->su_name.value);
 }
 
+
 /*****************************************************************************
  * Function: avd_su_si_assign_func
  *
@@ -1201,6 +1286,21 @@ void avd_su_si_assign_evh(AVD_CL_CB *cb,
                                su->su_on_node->su_cnt_admin_oper = 0;
                        }
                        /* else admin oper still not complete */
+               } else if ((su->sg_of_su->sg_ncs_spec == false) && 
((su->su_on_node->admin_ng != NULL) ||
+                                       
(su->sg_of_su->ng_using_saAmfSGAdminState == true))) {
+                       AVD_AMF_NG *ng = su->su_on_node->admin_ng;
+                       //Got response from AMFND for assignments decrement 
su_cnt_admin_oper.
+                       if ((ng != NULL) &&
+                               (((((ng->admin_ng_pend_cbk.admin_oper == 
SA_AMF_ADMIN_SHUTDOWN) ||
+                               (ng->admin_ng_pend_cbk.admin_oper == 
SA_AMF_ADMIN_LOCK)) &&
+                               (su->saAmfSUNumCurrActiveSIs == 0) && 
(su->saAmfSUNumCurrStandbySIs == 0) &&
+                               (AVSV_SUSI_ACT_DEL == 
n2d_msg->msg_info.n2d_su_si_assign.msg_act))) ||
+                                       (ng->admin_ng_pend_cbk.admin_oper == 
SA_AMF_ADMIN_UNLOCK))) {
+                               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);
+                       }
+                       process_su_si_response_for_ng(su, SA_AIS_OK);
                } else {
                        if (n2d_msg->msg_info.n2d_su_si_assign.error == 
NCSCC_RC_SUCCESS) {
                                if ((su->sg_of_su->sg_redundancy_model == 
SA_AMF_N_WAY_REDUNDANCY_MODEL) && 
@@ -1796,6 +1896,12 @@ void avd_node_down_appl_susi_failover(AV
 
        }
 
+       /* If this node-failover/nodereboot occurs dueing nodegroup operation 
then check 
+          if this leads to completion of operation and try to reply to imm.*/
+       if ((avnd->list_of_su != NULL) && (avnd->admin_ng != NULL)) {
+               avnd->su_cnt_admin_oper = 0;
+               process_su_si_response_for_ng(avnd->list_of_su, SA_AIS_OK);
+       }
        TRACE_LEAVE();
 }
 
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
@@ -1969,7 +1969,8 @@ bool AVD_SU::is_in_service(void) {
                        (node->saAmfNodeOperState == 
SA_AMF_OPERATIONAL_ENABLED) &&
                        (saAmfSUOperState == SA_AMF_OPERATIONAL_ENABLED) &&
                        ((saAmfSUPresenceState == SA_AMF_PRESENCE_INSTANTIATED 
||
-                                       saAmfSUPresenceState == 
SA_AMF_PRESENCE_RESTARTING));
+                                       saAmfSUPresenceState == 
SA_AMF_PRESENCE_RESTARTING)) &&
+                       (are_all_ngs_in_unlocked_state(node));
     } else {
             return (avd_cluster->saAmfClusterAdminState == 
SA_AMF_ADMIN_UNLOCKED) &&
                        (app->saAmfApplicationAdminState == 
SA_AMF_ADMIN_UNLOCKED) &&
@@ -1977,7 +1978,8 @@ bool AVD_SU::is_in_service(void) {
                        (sg->saAmfSGAdminState == SA_AMF_ADMIN_UNLOCKED) &&
                        (node->saAmfNodeAdminState == SA_AMF_ADMIN_UNLOCKED) &&
                        (node->saAmfNodeOperState == 
SA_AMF_OPERATIONAL_ENABLED) &&
-                       (saAmfSUOperState == SA_AMF_OPERATIONAL_ENABLED);
+                       (saAmfSUOperState == SA_AMF_OPERATIONAL_ENABLED) &&
+                       (are_all_ngs_in_unlocked_state(node));
     }
 }
 
@@ -1999,7 +2001,8 @@ bool AVD_SU::is_instantiable(void) {
                         (node->saAmfNodeAdminState == SA_AMF_ADMIN_UNLOCKED) &&
                         (node->saAmfNodeOperState == 
SA_AMF_OPERATIONAL_ENABLED) &&
                         (saAmfSUOperState == SA_AMF_OPERATIONAL_ENABLED) &&
-                       (saAmfSUPresenceState == 
SA_AMF_PRESENCE_UNINSTANTIATED);
+                       (saAmfSUPresenceState == 
SA_AMF_PRESENCE_UNINSTANTIATED) &&
+                       (are_all_ngs_in_unlocked_state(node));
 }
 
 void AVD_SU::set_saAmfSUPreInstantiable(bool value) {
@@ -2075,3 +2078,66 @@ void AVD_SU::complete_admin_op(SaAisErro
                pend_cbk.admin_oper = static_cast<SaAmfAdminOperationIdT>(0);
        }
 }
+/**
+ * @brief    Checks if modification of assignment is sent for any SUSI in SU.
+ * @result   true/false  
+ */
+bool AVD_SU::any_susi_fsm_in_modify()
+{
+        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;
+}
+/**
+ * @brief  Verify if SU is stable for admin operation on any higher 
+           level enity like SG, Node and Nodegroup etc.  
+ * @param  ptr to su(AVD_SU).
+ * @Return SA_AIS_OK/SA_AIS_ERR_TRY_AGAIN/SA_AIS_ERR_BAD_OPERATION.
+ *
+ * TODO: Such checks are present in node.cc and sg.cc also.
+   Replace such checks by this function call as a part of refactoring.
+*/
+SaAisErrorT AVD_SU::check_su_stability()
+{
+       SaAisErrorT rc = SA_AIS_OK;
+
+       if (pend_cbk.admin_oper != 0) {
+               LOG_NO("'%s' undergoing admin operation", name.value);
+               rc = SA_AIS_ERR_TRY_AGAIN;
+               goto done;
+       }
+       if ((saAmfSUPresenceState == SA_AMF_PRESENCE_INSTANTIATING) ||
+                       (saAmfSUPresenceState == SA_AMF_PRESENCE_TERMINATING) ||
+                       (saAmfSUPresenceState == SA_AMF_PRESENCE_RESTARTING)) {
+               LOG_NO("'%s' has presence state '%u'", 
name.value,saAmfSUPresenceState);
+               rc = SA_AIS_ERR_TRY_AGAIN;
+               goto done;
+       }
+       if ((saAmfSUPresenceState == SA_AMF_PRESENCE_INSTANTIATION_FAILED) ||
+                       (saAmfSUPresenceState == 
SA_AMF_PRESENCE_TERMINATION_FAILED)) {
+               LOG_NO("'%s' is in repair pending state", name.value);
+               rc = SA_AIS_ERR_BAD_OPERATION;
+               goto done;
+       }
+       for (AVD_COMP *comp = list_of_comp; comp; comp = comp->su_comp_next) {
+               rc = check_comp_stability(comp);
+               if (rc != SA_AIS_OK)
+                       goto done;
+        }
+done:
+       return rc;
+}
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
@@ -117,6 +117,14 @@
                        <flag>SA_INITIALIZED</flag>
                        <flag>SA_WRITABLE</flag>
                </attr>
+               <attr>
+                       <name>saAmfNGAdminState</name>
+                       <type>SA_UINT32_T</type>
+                       <category>SA_RUNTIME</category>
+                       <flag>SA_PERSISTENT</flag>
+                       <flag>SA_CACHED</flag>
+                       <default-value>1</default-value>
+               </attr>
        </class>
        <class name="SaAmfNodeSwBundle">
                <category>SA_CONFIG</category>

------------------------------------------------------------------------------
Dive into the World of Parallel Programming The Go Parallel Website, sponsored
by Intel and developed in partnership with Slashdot Media, is your hub for all
things parallel software development, from weekly thought leadership blogs to
news, videos, case studies, tutorials and more. Take a look and join the 
conversation now. http://goparallel.sourceforge.net/
_______________________________________________
Opensaf-devel mailing list
Opensaf-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to