osaf/libs/common/amf/d2nedu.c                  |  15 ++++-
 osaf/libs/common/amf/d2nmsg.c                  |  12 ++++
 osaf/libs/common/amf/include/amf_d2nmsg.h      |  13 ++++
 osaf/services/saf/amf/amfd/comp.cc             |   2 +-
 osaf/services/saf/amf/amfd/include/su.h        |   2 +-
 osaf/services/saf/amf/amfd/include/util.h      |   1 +
 osaf/services/saf/amf/amfd/mds.cc              |   2 +-
 osaf/services/saf/amf/amfd/sgproc.cc           |   2 +-
 osaf/services/saf/amf/amfd/su.cc               |  35 +++++++++++-
 osaf/services/saf/amf/amfd/util.cc             |  74 ++++++++++++++++++++++++++
 osaf/services/saf/amf/amfnd/clc.cc             |  28 ++++++---
 osaf/services/saf/amf/amfnd/err.cc             |  20 +++++-
 osaf/services/saf/amf/amfnd/evt.cc             |   2 +
 osaf/services/saf/amf/amfnd/include/avnd_evt.h |   1 +
 osaf/services/saf/amf/amfnd/include/avnd_mds.h |   4 +-
 osaf/services/saf/amf/amfnd/include/avnd_su.h  |   3 +
 osaf/services/saf/amf/amfnd/main.cc            |   1 +
 osaf/services/saf/amf/amfnd/mds.cc             |   6 +-
 osaf/services/saf/amf/amfnd/su.cc              |  46 ++++++++++++++++
 osaf/services/saf/amf/amfnd/susm.cc            |  10 ++-
 20 files changed, 252 insertions(+), 27 deletions(-)


This patch implements section 3.11.1.4.2 of AMF spec (Restrictions to
Auto-Repair).

diff --git a/osaf/libs/common/amf/d2nedu.c b/osaf/libs/common/amf/d2nedu.c
--- a/osaf/libs/common/amf/d2nedu.c
+++ b/osaf/libs/common/amf/d2nedu.c
@@ -414,6 +414,16 @@ uint32_t avsv_edp_dnd_msg(EDU_HDL *hdl, 
                {EDU_EXEC, avsv_edp_csi_attr_info, 0, 0, 0,
                 
(long)&((AVSV_DND_MSG*)0)->msg_info.d2n_compcsi_assign_msg_info.info.attrs, 0, 
NULL},
 
+               /*AVSV_D2N_SU_MAINTENANCE_MSG_INFO*/
+               {EDU_EXEC, ncs_edp_uns32, 0, 0, 0,
+        (long)&((AVSV_DND_MSG 
*)0)->msg_info.d2n_su_maintenance_msg_info.msg_id, 0, NULL},
+    {EDU_EXEC, m_NCS_EDP_SACLMNODEIDT, 0, 0, 0,
+        (long)&((AVSV_DND_MSG 
*)0)->msg_info.d2n_su_maintenance_msg_info.node_id, 0, NULL},
+               {EDU_EXEC, ncs_edp_sanamet, 0, 0, 0, 
+                   
(long)&((AVSV_DND_MSG*)0)->msg_info.d2n_su_maintenance_msg_info.su, 0, NULL},
+               {EDU_EXEC, ncs_edp_sanamet, 0, 0, EDU_EXIT, 
+                   
(long)&((AVSV_DND_MSG*)0)->msg_info.d2n_su_maintenance_msg_info.suMaintenanceCampaign,
 0, NULL},
+
                {EDU_END, 0, 0, 0, 0, 0, 0, NULL},
        };
 
@@ -482,7 +492,8 @@ int avsv_dnd_msg_test_type_fnc(NCSCONTEX
                LCL_JMP_OFFSET_AVSV_D2N_REBOOT_MSG = 123,
                LCL_JMP_OFFSET_AVSV_N2D_ND_SISU_STATE_INFO_MSG = 125,
                LCL_JMP_OFFSET_AVSV_N2D_ND_CSICOMP_STATE_INFO_MSG = 131,
-               LCL_JMP_OFFSET_AVSV_D2N_COMPCSI_ASSIGN_MSG = 137
+               LCL_JMP_OFFSET_AVSV_D2N_COMPCSI_ASSIGN_MSG = 137,
+               LCL_JMP_OFFSET_AVSV_D2N_SU_MAINTENANCE_MSG = 143
        };
        AVSV_DND_MSG_TYPE type;
 
@@ -554,6 +565,8 @@ int avsv_dnd_msg_test_type_fnc(NCSCONTEX
                return LCL_JMP_OFFSET_AVSV_N2D_ND_CSICOMP_STATE_INFO_MSG ;
        case AVSV_D2N_COMPCSI_ASSIGN_MSG:
                return LCL_JMP_OFFSET_AVSV_D2N_COMPCSI_ASSIGN_MSG;
+       case AVSV_D2N_SU_MAINTENANCE_MSG:
+               return LCL_JMP_OFFSET_AVSV_D2N_SU_MAINTENANCE_MSG;
 
        default:
                break;
diff --git a/osaf/libs/common/amf/d2nmsg.c b/osaf/libs/common/amf/d2nmsg.c
--- a/osaf/libs/common/amf/d2nmsg.c
+++ b/osaf/libs/common/amf/d2nmsg.c
@@ -513,6 +513,15 @@ static void free_d2n_compcsi_info(AVSV_D
 
 }
 
+static void free_d2n_su_maintenance_info(AVSV_DND_MSG *su_maintenance_msg)
+{
+  AVSV_D2N_SU_MAINTENANCE_MSG_INFO *su_maintenance =
+    &su_maintenance_msg->msg_info.d2n_su_maintenance_msg_info;
+
+       osaf_extended_name_free(&su_maintenance->su);
+       osaf_extended_name_free(&su_maintenance->suMaintenanceCampaign);
+}
+
 /****************************************************************************
   Name          : avsv_dnd_msg_free
  
@@ -609,6 +618,9 @@ void avsv_dnd_msg_free(AVSV_DND_MSG *msg
        case AVSV_D2N_COMPCSI_ASSIGN_MSG:
                free_d2n_compcsi_info(msg);
                break;
+       case AVSV_D2N_SU_MAINTENANCE_MSG:
+               free_d2n_su_maintenance_info(msg);
+               break;
        default:
                break;
        }
diff --git a/osaf/libs/common/amf/include/amf_d2nmsg.h 
b/osaf/libs/common/amf/include/amf_d2nmsg.h
--- a/osaf/libs/common/amf/include/amf_d2nmsg.h
+++ b/osaf/libs/common/amf/include/amf_d2nmsg.h
@@ -51,6 +51,7 @@ extern "C" {
 #define AVSV_AVD_AVND_MSG_FMT_VER_5    5
 #define AVSV_AVD_AVND_MSG_FMT_VER_6    6
 #define AVSV_AVD_AVND_MSG_FMT_VER_7    7
+#define AVSV_AVD_AVND_MSG_FMT_VER_8    8
 
 /* Internode/External Components Validation result */
 typedef enum {
@@ -108,6 +109,7 @@ typedef enum {
        AVSV_N2D_ND_SISU_STATE_INFO_MSG,
        AVSV_N2D_ND_CSICOMP_STATE_INFO_MSG,
        AVSV_D2N_COMPCSI_ASSIGN_MSG,
+       AVSV_D2N_SU_MAINTENANCE_MSG,
        AVSV_DND_MSG_MAX
 } AVSV_DND_MSG_TYPE;
 
@@ -647,6 +649,16 @@ typedef struct avsv_d2n_compcsi_assign_m
        } info; 
 } AVSV_D2N_COMPCSI_ASSIGN_MSG_INFO;
 
+/*
+ * Message structure to send updates to saAmfSUMaintenanceCampaign.
+ */
+typedef struct avsv_d2n_su_maintenance_msg {
+       uint32_t msg_id;
+       SaClmNodeIdT node_id;
+  SaNameT su;
+  SaNameT suMaintenanceCampaign;
+} AVSV_D2N_SU_MAINTENANCE_MSG_INFO;
+
 typedef struct avsv_dnd_msg {
        AVSV_DND_MSG_TYPE msg_type;
        union {
@@ -681,6 +693,7 @@ typedef struct avsv_dnd_msg {
                AVSV_D2N_HB_MSG_INFO d2n_hb_info;
                AVSV_D2N_REBOOT_MSG_INFO d2n_reboot_info;
                AVSV_D2N_COMPCSI_ASSIGN_MSG_INFO d2n_compcsi_assign_msg_info;
+               AVSV_D2N_SU_MAINTENANCE_MSG_INFO d2n_su_maintenance_msg_info;
        } msg_info;
 } AVSV_DND_MSG;
 
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
@@ -155,7 +155,7 @@ void AVD_COMP::avd_comp_pres_state_set(S
                 (saAmfCompPresenceState == 
SA_AMF_PRESENCE_TERMINATION_FAILED)) ||
                 ((node->saAmfNodeFailfastOnInstantiationFailure == true) && 
                  (saAmfCompPresenceState == 
SA_AMF_PRESENCE_INSTANTIATION_FAILED))) &&
-      (!su->saAmfSUMaintenanceCampaign.empty())) {
+      (su->saAmfSUMaintenanceCampaign.empty())) {
 
                saflog(LOG_NOTICE, amfSvcUsrName, "%s PresenceState %s => %s",
                                osaf_extended_name_borrow(&comp_info.name), 
avd_pres_state_name[old_state],
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
@@ -116,7 +116,7 @@ class AVD_SU {
        void set_term_state(bool state);
        void remove_from_model();
        void set_su_switch(SaToggleState state, bool wrt_to_imm = true);
-       AVD_AVND *get_node_ptr(void);
+       AVD_AVND *get_node_ptr(void) const;
        bool is_in_service(void);
        bool is_instantiable(void);
        void reset_all_comps_assign_flag();
diff --git a/osaf/services/saf/amf/amfd/include/util.h 
b/osaf/services/saf/amf/amfd/include/util.h
--- a/osaf/services/saf/amf/amfd/include/util.h
+++ b/osaf/services/saf/amf/amfd/include/util.h
@@ -102,5 +102,6 @@ extern const char *admin_op_name(SaAmfAd
 int compare_sanamet(const std::string& lhs, const std::string& rhs);
 uint32_t avd_snd_compcsi_msg(AVD_COMP *comp, AVD_CSI *csi,
                avd_comp_csi_rel_tag *compcsi, AVSV_COMPCSI_ACT act);
+uint32_t avd_snd_su_maintenance_msg(const AVD_SU&);
 
 #endif
diff --git a/osaf/services/saf/amf/amfd/mds.cc 
b/osaf/services/saf/amf/amfd/mds.cc
--- a/osaf/services/saf/amf/amfd/mds.cc
+++ b/osaf/services/saf/amf/amfd/mds.cc
@@ -46,7 +46,7 @@ const MDS_CLIENT_MSG_FORMAT_VER avd_avnd
        AVSV_AVD_AVND_MSG_FMT_VER_1, AVSV_AVD_AVND_MSG_FMT_VER_2,
        AVSV_AVD_AVND_MSG_FMT_VER_3, AVSV_AVD_AVND_MSG_FMT_VER_4,
        AVSV_AVD_AVND_MSG_FMT_VER_5, AVSV_AVD_AVND_MSG_FMT_VER_6,
-       AVSV_AVD_AVND_MSG_FMT_VER_7
+       AVSV_AVD_AVND_MSG_FMT_VER_7, AVSV_AVD_AVND_MSG_FMT_VER_8
 };
 
 const MDS_CLIENT_MSG_FORMAT_VER avd_avd_msg_fmt_map_table[] = {
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
@@ -804,7 +804,7 @@ void avd_su_oper_state_evh(AVD_CL_CB *cb
                                node->recvr_fail_sw = true;
 
         // if maintenance campaign is ongoing, disable node reboot
-        if (su->saAmfSUMaintenanceCampaign.empty())
+        if (!su->saAmfSUMaintenanceCampaign.empty())
           node_reboot_req = false;
 
                                switch 
(n2d_msg->msg_info.n2d_opr_state.rec_rcvr.raw) {
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
@@ -737,7 +737,7 @@ void AVD_SU::set_pres_state(SaAmfPresenc
                        (su_on_node->saAmfNodeFailfastOnTerminationFailure == 
true) &&
                        (sg_of_su->saAmfSGAutoRepair == true) &&
                        (su_on_node->saAmfNodeAutoRepair == true) &&
-      (!saAmfSUMaintenanceCampaign.empty()))
+      (saAmfSUMaintenanceCampaign.empty()))
                /* According to AMF B.04.01 Section 4.8 Page 214 if user 
configures
                   saAmfNodeFailfastOnTerminationFailure = true, AMF has to 
perform
                   node failfast recovery action. So mark SU to 
SA_AMF_PRESENCE_TERMINATION_FAILED 
@@ -748,7 +748,7 @@ void AVD_SU::set_pres_state(SaAmfPresenc
                        (su_on_node->saAmfNodeFailfastOnInstantiationFailure == 
true) &&
                        (sg_of_su->saAmfSGAutoRepair == true) &&
                        (su_on_node->saAmfNodeAutoRepair == true) &&
-      (!saAmfSUMaintenanceCampaign.empty())) 
+      (saAmfSUMaintenanceCampaign.empty())) 
                /* According to AMF B.04.01 Section 4.6 Page 212 if user 
configures
                   saAmfNodeFailfastOnInstantiationFailure = true, AMF has to 
perform
                   node failfast recovery action. So mark SU to 
SA_AMF_PRESENCE_INSTANTIATION_FAILED
@@ -1782,6 +1782,32 @@ static SaAisErrorT su_ccb_completed_cb(C
        return rc;
 }
 
+static void sendMaintenanceUpdateToND(const AVD_SU& su) {
+  do {
+    auto it(nds_mds_ver_db.find(
+      su.su_on_node->node_info.nodeId));
+
+    if (it == nds_mds_ver_db.end())
+      break;
+
+    // Check if this amfnd is capable of this functionality.
+    if (it->second < AVSV_AVD_AVND_MSG_FMT_VER_8) {
+      TRACE_3("not sending to '%s' on :%x with mds version:'%u'",
+              su.name.c_str(),
+              su.su_on_node->node_info.nodeId,
+              it->second);
+      break;
+    }
+
+    TRACE_3("sending to '%s' on :%x with mds version:'%u'",
+            su.name.c_str(),
+            su.su_on_node->node_info.nodeId,
+            it->second);
+
+    avd_snd_su_maintenance_msg(su);
+  } while (false);
+}
+
 /*****************************************************************************
  * Function: avd_su_ccb_apply_modify_hdlr
  * 
@@ -1840,6 +1866,9 @@ static void su_ccb_apply_modify_hdlr(str
                                TRACE("saAmfSUMaintenanceCampaign set to '%s' 
for '%s'",
                                          
su->saAmfSUMaintenanceCampaign.c_str(), su->name.c_str());
                        }
+
+      if (avd_cb->avail_state_avd == SA_AMF_HA_ACTIVE)
+        sendMaintenanceUpdateToND(*su);
                } else if (!strcmp(attr_mod->modAttr.attrName, "saAmfSUType")) {
                        AVD_SUTYPE *sut;
                        SaNameT sutype_name = *(SaNameT*) 
attr_mod->modAttr.attrValues[0];
@@ -2165,7 +2194,7 @@ void AVD_SU::set_su_switch(SaToggleState
        m_AVSV_SEND_CKPT_UPDT_ASYNC_UPDT(avd_cb, this, AVSV_CKPT_SU_SWITCH);
 }
 
-AVD_AVND *AVD_SU::get_node_ptr(void) {
+AVD_AVND *AVD_SU::get_node_ptr(void) const {
         if (su_is_external == true)
                 return avd_cb->ext_comp_info.local_avnd_node;
         else
diff --git a/osaf/services/saf/amf/amfd/util.cc 
b/osaf/services/saf/amf/amfd/util.cc
--- a/osaf/services/saf/amf/amfd/util.cc
+++ b/osaf/services/saf/amf/amfd/util.cc
@@ -1764,6 +1764,14 @@ static void free_d2n_compcsi_info(AVSV_D
   }
 }
 
+static void free_d2n_su_maintenance_info(AVSV_DND_MSG *su_maintenance_msg) {
+  AVSV_D2N_SU_MAINTENANCE_MSG_INFO *su_maintenance(
+    &su_maintenance_msg->msg_info.d2n_su_maintenance_msg_info);
+
+  osaf_extended_name_free(&su_maintenance->su);
+  osaf_extended_name_free(&su_maintenance->suMaintenanceCampaign);
+}
+
 /****************************************************************************
   Name          : d2n_msg_free
  
@@ -1815,6 +1823,9 @@ void d2n_msg_free(AVSV_DND_MSG *msg)
        case AVSV_D2N_COMPCSI_ASSIGN_MSG:
                free_d2n_compcsi_info(msg);
                break;
+       case AVSV_D2N_SU_MAINTENANCE_MSG:
+               free_d2n_su_maintenance_info(msg);
+               break;
        default:
                break;
        }
@@ -2096,3 +2107,66 @@ uint32_t avd_snd_compcsi_msg(AVD_COMP *c
   return NCSCC_RC_SUCCESS;
 }
 
+/**
+ * @brief    Sends a message to AMFND for a change in SUMaintenanceCampaign
+ * @param    ptr to su 
+ * @param    act(action of type AVSV_COMPCSI_ACT) 
+ * @return   NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE. 
+ */
+uint32_t avd_snd_su_maintenance_msg(const AVD_SU& su) {
+  TRACE_ENTER2("'%s', '%s'",
+               su.name.c_str(),
+               su.saAmfSUMaintenanceCampaign.c_str());
+
+  uint32_t rc(NCSCC_RC_SUCCESS);
+
+  do {
+    AVD_AVND *avnd(su.get_node_ptr());
+
+    if (avnd->node_state == AVD_AVND_STATE_ABSENT ||
+        avnd->node_state == AVD_AVND_STATE_GO_DOWN) {
+      break;
+    }
+
+    // Will be freed in free_d2n_su_maintenance_info()
+    SaNameT su_name;
+    osaf_extended_name_alloc(su.name.c_str(), &su_name);
+
+    // Will be freed in free_d2n_su_maintenance_info()
+    SaNameT suMaintenanceCampaign;
+    osaf_extended_name_alloc(su.saAmfSUMaintenanceCampaign.c_str(),
+                             &suMaintenanceCampaign);
+
+    // prepare the SU_MAINTENANCE message
+    AVD_DND_MSG *su_maintenance_msg(new AVSV_DND_MSG);
+    su_maintenance_msg->msg_type = AVSV_D2N_SU_MAINTENANCE_MSG;
+    su_maintenance_msg->msg_info.d2n_su_maintenance_msg_info.node_id =
+      avnd->node_info.nodeId;
+    su_maintenance_msg->msg_info.d2n_su_maintenance_msg_info.su = su_name;
+    
su_maintenance_msg->msg_info.d2n_su_maintenance_msg_info.suMaintenanceCampaign =
+      suMaintenanceCampaign;
+
+    // Generate new msg_id.
+    su_maintenance_msg->msg_info.d2n_su_maintenance_msg_info.msg_id =
+      ++(avnd->snd_msg_id);
+
+    // Send SU_MAINTENANCE message*/
+    TRACE("Sending %u to %x",
+          AVSV_D2N_SU_MAINTENANCE_MSG,
+          avnd->node_info.nodeId);
+
+    if (avd_d2n_msg_snd(avd_cb, avnd, su_maintenance_msg) != NCSCC_RC_SUCCESS) 
{
+      LOG_ER("Send to %x failed",avnd->node_info.nodeId);
+      --(avnd->snd_msg_id);
+      d2n_msg_free(su_maintenance_msg);
+      rc = NCSCC_RC_FAILURE;
+      break;
+    }
+
+    // Checkpoint to standby AMFD.
+    m_AVSV_SEND_CKPT_UPDT_ASYNC_UPDT(avd_cb, avnd, AVSV_CKPT_AVND_SND_MSG_ID);
+  } while (false);
+
+  TRACE_LEAVE();
+  return rc;
+}
diff --git a/osaf/services/saf/amf/amfnd/clc.cc 
b/osaf/services/saf/amf/amfnd/clc.cc
--- a/osaf/services/saf/amf/amfnd/clc.cc
+++ b/osaf/services/saf/amf/amfnd/clc.cc
@@ -970,19 +970,29 @@ uint32_t avnd_comp_clc_st_chng_prc(AVND_
        if (comp->su->is_ncs == true) {
                if(SA_AMF_PRESENCE_INSTANTIATION_FAILED == final_st) {
                        LOG_ER("'%s'got Inst failed", comp->name.c_str());
-                       opensaf_reboot(avnd_cb->node_info.nodeId,
-                                                       
osaf_extended_name_borrow(&avnd_cb->node_info.executionEnvironment),
-                                                       "NCS component 
Instantiation failed");
-                       LOG_ER("Amfnd is exiting (due to ncs comp inst failed) 
to aid fast reboot");
-                       exit(0);
+      if (comp->su->suMaintenanceCampaign.empty()) {
+                         opensaf_reboot(avnd_cb->node_info.nodeId,
+                                                         
osaf_extended_name_borrow(&avnd_cb->node_info.executionEnvironment),
+                                                         "NCS component 
Instantiation failed");
+                         LOG_ER("Amfnd is exiting (due to ncs comp inst 
failed) to aid fast reboot");
+                         exit(0);
+      } else {
+        LOG_NO("not rebooting as maintenance campaign is ongoing");
+        goto done;
+      }
                }
                if(SA_AMF_PRESENCE_TERMINATION_FAILED == final_st) {
                        LOG_ER("'%s'got Term failed", comp->name.c_str());
-                       opensaf_reboot(avnd_cb->node_info.nodeId,
+      if (comp->su->suMaintenanceCampaign.empty()) {
+                         opensaf_reboot(avnd_cb->node_info.nodeId,
                                                        
osaf_extended_name_borrow(&avnd_cb->node_info.executionEnvironment),
-                                                       "NCS component 
Termination failed");
-                       LOG_ER("Amfnd is exiting (due to ncs comp term failed) 
to aid fast reboot");
-                       exit(0);
+                                                         "NCS component 
Termination failed");
+                         LOG_ER("Amfnd is exiting (due to ncs comp term 
failed) to aid fast reboot");
+                         exit(0);
+      } else {
+        LOG_NO("not rebooting as maintenance campaign is ongoing");
+        goto done;
+      }
                }
        }
 
diff --git a/osaf/services/saf/amf/amfnd/err.cc 
b/osaf/services/saf/amf/amfnd/err.cc
--- a/osaf/services/saf/amf/amfnd/err.cc
+++ b/osaf/services/saf/amf/amfnd/err.cc
@@ -407,8 +407,14 @@ uint32_t avnd_err_process(AVND_CB *cb, A
                LOG_ER("%s Faulted due to:%s Recovery is:%s",
                       comp->name.c_str(), g_comp_err[comp->err_info.src], 
g_comp_rcvr[esc_rcvr - 1]);
                /* do the local node reboot for node_failfast or ncs component 
failure*/
-               opensaf_reboot(avnd_cb->node_info.nodeId, 
osaf_extended_name_borrow(&avnd_cb->node_info.executionEnvironment),
+    if (comp->su->suMaintenanceCampaign.empty()) {
+                 opensaf_reboot(avnd_cb->node_info.nodeId, 
osaf_extended_name_borrow(&avnd_cb->node_info.executionEnvironment),
                                "Component faulted: recovery is node failfast");
+    } else {
+      LOG_NO("not rebooting because maintenance campaign is set: %s",
+             comp->su->suMaintenanceCampaign.c_str());
+      goto done;
+    }
        }
 
        /* execute the recovery */
@@ -1038,11 +1044,17 @@ uint32_t avnd_err_rcvr_node_failover(AVN
                rc = avnd_comp_clc_fsm_run(cb, comp, 
AVND_COMP_CLC_PRES_FSM_EV_CLEANUP);
                if (rc != NCSCC_RC_SUCCESS) {
                        LOG_ER("'%s' termination failed", comp->name.c_str());
-                       opensaf_reboot(avnd_cb->node_info.nodeId,
+      if (comp->su->suMaintenanceCampaign.empty()) {
+                         opensaf_reboot(avnd_cb->node_info.nodeId,
                                                   
osaf_extended_name_borrow(&avnd_cb->node_info.executionEnvironment),
                                                   "Component termination 
failed at node failover");
-                       LOG_ER("Exiting (due to comp term failed) to aid fast 
node reboot");
-                       exit(1);
+                         LOG_ER("Exiting (due to comp term failed) to aid fast 
node reboot");
+                         exit(1);
+      } else {
+        LOG_NO("not rebooting because maintenance campaign is set: %s",
+               comp->su->suMaintenanceCampaign.c_str());
+        continue;
+      }
                }
                avnd_su_pres_state_set(cb, comp->su, 
SA_AMF_PRESENCE_TERMINATING);
        }
diff --git a/osaf/services/saf/amf/amfnd/evt.cc 
b/osaf/services/saf/amf/amfnd/evt.cc
--- a/osaf/services/saf/amf/amfnd/evt.cc
+++ b/osaf/services/saf/amf/amfnd/evt.cc
@@ -88,6 +88,7 @@ AVND_EVT *avnd_evt_create(AVND_CB *cb,
        case AVND_EVT_AVD_ADMIN_OP_REQ_MSG:
        case AVND_EVT_AVD_REBOOT_MSG:
        case AVND_EVT_AVD_COMPCSI_ASSIGN_MSG:
+       case AVND_EVT_AVD_SU_MAINTENANCE_MSG:
                evt->info.avd = (AVSV_DND_MSG *)info;
                break;
 
@@ -237,6 +238,7 @@ void avnd_evt_destroy(AVND_EVT *evt)
        case AVND_EVT_AVD_HEARTBEAT_MSG:
        case AVND_EVT_AVD_REBOOT_MSG:
        case AVND_EVT_AVD_COMPCSI_ASSIGN_MSG:
+       case AVND_EVT_AVD_SU_MAINTENANCE_MSG:
                if (evt->info.avd)
                        avsv_dnd_msg_free(evt->info.avd);
                break;
diff --git a/osaf/services/saf/amf/amfnd/include/avnd_evt.h 
b/osaf/services/saf/amf/amfnd/include/avnd_evt.h
--- a/osaf/services/saf/amf/amfnd/include/avnd_evt.h
+++ b/osaf/services/saf/amf/amfnd/include/avnd_evt.h
@@ -53,6 +53,7 @@ typedef enum avnd_evt_type {
        AVND_EVT_AVD_HEARTBEAT_MSG,
        AVND_EVT_AVD_REBOOT_MSG,
        AVND_EVT_AVD_COMPCSI_ASSIGN_MSG,
+       AVND_EVT_AVD_SU_MAINTENANCE_MSG,
        AVND_EVT_AVD_MAX,
 
        /* AvA event types */
diff --git a/osaf/services/saf/amf/amfnd/include/avnd_mds.h 
b/osaf/services/saf/amf/amfnd/include/avnd_mds.h
--- a/osaf/services/saf/amf/amfnd/include/avnd_mds.h
+++ b/osaf/services/saf/amf/amfnd/include/avnd_mds.h
@@ -31,10 +31,10 @@
 #define AVND_MDS_H
 
 /* In Service upgrade support */
-#define AVND_MDS_SUB_PART_VERSION   7 
+#define AVND_MDS_SUB_PART_VERSION   8 
 
 #define AVND_AVD_SUBPART_VER_MIN   1
-#define AVND_AVD_SUBPART_VER_MAX   7 
+#define AVND_AVD_SUBPART_VER_MAX   8 
 
 #define AVND_AVND_SUBPART_VER_MIN   1
 #define AVND_AVND_SUBPART_VER_MAX   1
diff --git a/osaf/services/saf/amf/amfnd/include/avnd_su.h 
b/osaf/services/saf/amf/amfnd/include/avnd_su.h
--- a/osaf/services/saf/amf/amfnd/include/avnd_su.h
+++ b/osaf/services/saf/amf/amfnd/include/avnd_su.h
@@ -143,6 +143,8 @@ typedef struct avnd_su_tag {
        uint32_t si_active_cnt; /* no of active SIs assigned to this su */
        uint32_t si_standby_cnt;        /* no of standby SIs assigned to this 
su */
 
+  std::string suMaintenanceCampaign;
+
        /* 
         * Ordered comp list (based on inst level). Note that as the 
         * lexicographic key (comp-name) & the keys used for 
@@ -417,5 +419,6 @@ extern AVND_SU *avnd_sudb_rec_get(AmfDb<
 extern AVND_SU *avnd_sudb_rec_get_next(AmfDb<std::string, AVND_SU>& sudb, 
const std::string& name);
 extern void sudb_rec_comp_add(AVND_SU *su, AVND_COMP *comp, uint32_t *rc);
 uint32_t avnd_evt_avd_compcsi_evh(struct avnd_cb_tag *cb, struct avnd_evt_tag 
*evt);
+uint32_t avnd_evt_avd_su_maintenance_evh(avnd_cb_tag *, AVND_EVT *);
 
 #endif
diff --git a/osaf/services/saf/amf/amfnd/main.cc 
b/osaf/services/saf/amf/amfnd/main.cc
--- a/osaf/services/saf/amf/amfnd/main.cc
+++ b/osaf/services/saf/amf/amfnd/main.cc
@@ -69,6 +69,7 @@ extern const AVND_EVT_HDLR g_avnd_func_l
        avnd_evt_avd_hb_evh,            /* AVND_EVT_AVD_HEARTBEAT_MSG */
        avnd_evt_avd_reboot_evh,            /* /AVND_EVT_AVD_REBOOT_MSG */
        avnd_evt_avd_compcsi_evh, //AVND_EVT_AVD_COMPCSI_ASSIGN_MSG
+       avnd_evt_avd_su_maintenance_evh, //AVND_EVT_AVD_SU_MAINTENANCE_MSG
 
        /* AvA event types */
        avnd_evt_ava_finalize_evh,      /* AVND_EVT_AVA_AMF_FINALIZE */
diff --git a/osaf/services/saf/amf/amfnd/mds.cc 
b/osaf/services/saf/amf/amfnd/mds.cc
--- a/osaf/services/saf/amf/amfnd/mds.cc
+++ b/osaf/services/saf/amf/amfnd/mds.cc
@@ -42,7 +42,7 @@ const MDS_CLIENT_MSG_FORMAT_VER avnd_avd
        AVSV_AVD_AVND_MSG_FMT_VER_1, AVSV_AVD_AVND_MSG_FMT_VER_2,
        AVSV_AVD_AVND_MSG_FMT_VER_3, AVSV_AVD_AVND_MSG_FMT_VER_4,
        AVSV_AVD_AVND_MSG_FMT_VER_4, AVSV_AVD_AVND_MSG_FMT_VER_6,
-       AVSV_AVD_AVND_MSG_FMT_VER_7
+       AVSV_AVD_AVND_MSG_FMT_VER_7, AVSV_AVD_AVND_MSG_FMT_VER_8
 };
 
 /* messages from director */
@@ -50,7 +50,7 @@ const MDS_CLIENT_MSG_FORMAT_VER avd_avnd
        AVSV_AVD_AVND_MSG_FMT_VER_1, AVSV_AVD_AVND_MSG_FMT_VER_2,
        AVSV_AVD_AVND_MSG_FMT_VER_3, AVSV_AVD_AVND_MSG_FMT_VER_4,
        AVSV_AVD_AVND_MSG_FMT_VER_5, AVSV_AVD_AVND_MSG_FMT_VER_6,
-       AVSV_AVD_AVND_MSG_FMT_VER_7
+       AVSV_AVD_AVND_MSG_FMT_VER_7, AVSV_AVD_AVND_MSG_FMT_VER_8
 };
 
 const MDS_CLIENT_MSG_FORMAT_VER avnd_avnd_msg_fmt_map_table[] = {
@@ -404,6 +404,8 @@ uint32_t avnd_mds_rcv(AVND_CB *cb, MDS_C
 
                if (msg.info.avd->msg_type == AVSV_D2N_COMPCSI_ASSIGN_MSG)
                        type = AVND_EVT_AVD_COMPCSI_ASSIGN_MSG;
+               else if (msg.info.avd->msg_type == AVSV_D2N_SU_MAINTENANCE_MSG)
+                       type = AVND_EVT_AVD_SU_MAINTENANCE_MSG;
                else 
                        type = 
static_cast<AVND_EVT_TYPE>((msg.info.avd->msg_type - AVSV_D2N_NODE_UP_MSG) + 
AVND_EVT_AVD_NODE_UP_MSG);
                break;
diff --git a/osaf/services/saf/amf/amfnd/su.cc 
b/osaf/services/saf/amf/amfnd/su.cc
--- a/osaf/services/saf/amf/amfnd/su.cc
+++ b/osaf/services/saf/amf/amfnd/su.cc
@@ -1042,4 +1042,50 @@ done:
   return rc;
 }
 
+/**
+ * @brief  Processes su maintenance message from AMFD.
+ * @param  cb (ptr to AVND_CB)
+ * @param  evt(ptr to AVND_EVT)
+ *
+ * @return NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE.
+ */
+uint32_t avnd_evt_avd_su_maintenance_evh(AVND_CB *cb, AVND_EVT *evt) {
+  uint32_t rc(NCSCC_RC_SUCCESS);
 
+  do {
+    AVSV_D2N_SU_MAINTENANCE_MSG_INFO *su_maintenance(
+      &evt->info.avd->msg_info.d2n_su_maintenance_msg_info);
+
+    const std::string su_name(Amf::to_string(&su_maintenance->su));
+    const std::string suMaintenanceCampaign(Amf::to_string(
+      &su_maintenance->suMaintenanceCampaign));
+
+    TRACE_ENTER2("'%s', '%s'", su_name.c_str(), suMaintenanceCampaign.c_str());
+
+    AVND_SU *su(avnd_sudb_rec_get(cb->sudb, su_name));
+
+    if (!su) {
+      LOG_ER("su: '%s' not found", su_name.c_str());
+      break;
+    }
+
+    if (cb->term_state == AVND_TERM_STATE_OPENSAF_SHUTDOWN_INITIATED ||
+        cb->term_state == AVND_TERM_STATE_OPENSAF_SHUTDOWN_STARTED) {
+      LOG_NO("Shutdown started : Ignoring setting of su maintenance'%s'",
+             su->name.c_str());
+      break;
+    }
+
+    avnd_msgid_assert(su_maintenance->msg_id);
+    cb->rcv_msg_id = su_maintenance->msg_id;
+
+    TRACE("setting suMaintenanceCampaign to %s for su: %s",
+          suMaintenanceCampaign.c_str(),
+          su_name.c_str());
+
+    su->suMaintenanceCampaign = suMaintenanceCampaign;
+  } while (false);
+
+  TRACE_LEAVE2("%u", rc);
+  return rc;
+}
diff --git a/osaf/services/saf/amf/amfnd/susm.cc 
b/osaf/services/saf/amf/amfnd/susm.cc
--- a/osaf/services/saf/amf/amfnd/susm.cc
+++ b/osaf/services/saf/amf/amfnd/susm.cc
@@ -2787,8 +2787,14 @@ uint32_t avnd_su_pres_terming_comptermfa
 
        if (true == su->is_ncs) {
                std::string reason = "SU '" + su->name + "' Termination-failed";
-               opensaf_reboot(avnd_cb->node_info.nodeId, 
osaf_extended_name_borrow(&avnd_cb->node_info.executionEnvironment),
-                               reason.c_str());
+    if (su->suMaintenanceCampaign.empty()) {
+                 opensaf_reboot(avnd_cb->node_info.nodeId, 
osaf_extended_name_borrow(&avnd_cb->node_info.executionEnvironment),
+                                 reason.c_str());
+    } else {
+      LOG_ER("%s", reason.c_str());
+      LOG_NO("not rebooting because su maintenance campaign is set: %s",
+             su->suMaintenanceCampaign.c_str());
+    }
        }
 
  done:


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

Reply via email to