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