src/smf/smfd/SmfCampState.cc       |   68 ++++++++++
 src/smf/smfd/SmfCampState.h        |    7 +
 src/smf/smfd/SmfCampaignThread.cc  |  233 ++++++++++++++++++++++++++++++++++++-
 src/smf/smfd/SmfCampaignThread.h   |   15 ++
 src/smf/smfd/SmfStepTypes.cc       |   32 ++--
 src/smf/smfd/SmfUpgradeCampaign.cc |   20 +++
 src/smf/smfd/SmfUpgradeCampaign.h  |    7 +
 7 files changed, 363 insertions(+), 19 deletions(-)


This patch adds support for section 4.2.1.3 of SMF A.01.02 spec.

diff --git a/src/smf/smfd/SmfCampState.cc b/src/smf/smfd/SmfCampState.cc
--- a/src/smf/smfd/SmfCampState.cc
+++ b/src/smf/smfd/SmfCampState.cc
@@ -191,6 +191,18 @@ SmfCampState::commit(SmfUpgradeCampaign 
 }
 
 
//------------------------------------------------------------------------------
+// asyncFailure()
+//------------------------------------------------------------------------------
+SmfCampResultT 
+SmfCampState::asyncFailure(SmfUpgradeCampaign *  i_camp)
+{
+       TRACE_ENTER();
+       LOG_NO("SmfCampState::asyncFailure default implementation. No state 
change");
+       TRACE_LEAVE();
+        return SMF_CAMP_DONE;
+}
+
+//------------------------------------------------------------------------------
 // procResult()
 
//------------------------------------------------------------------------------
 SmfCampResultT 
@@ -926,6 +938,37 @@ SmfCampStateExecuting::suspend(SmfUpgrad
 }
 
 
//------------------------------------------------------------------------------
+// asyncFailure()
+//------------------------------------------------------------------------------
+SmfCampResultT 
+SmfCampStateExecuting::asyncFailure(SmfUpgradeCampaign * i_camp)
+{
+       TRACE_ENTER();
+       TRACE("SmfCampStateExecuting::asyncFailure implementation");
+
+       /* Send suspend message to all procedures */
+        std::vector<SmfUpgradeProcedure*> procedures = i_camp->getProcedures();
+
+       std::vector < SmfUpgradeProcedure * >::iterator iter;
+
+       for (iter = procedures.begin(); iter != procedures.end(); ++iter) {
+                TRACE("SmfCampStateExecuting::Procedure %s, send suspend",
+                      (*iter)->getProcName().c_str());
+                SmfProcedureThread *procThread = (*iter)->getProcThread();
+                PROCEDURE_EVT *evt = new PROCEDURE_EVT();
+                evt->type = PROCEDURE_EVT_SUSPEND;
+                procThread->send(evt);
+       }
+
+        i_camp->m_noOfProcResponses = 0;
+        changeState(i_camp, SmfCampStateErrorDetected::instance());
+        /* Wait for suspend responses from all procedures 
(SmfCampStateSuspendingExec::procResult) */
+
+       TRACE_LEAVE();
+        return SMF_CAMP_SUSPENDING; 
+}
+
+//------------------------------------------------------------------------------
 // procResult()
 
//------------------------------------------------------------------------------
 SmfCampResultT 
@@ -1215,6 +1258,19 @@ SmfCampStateSuspendingExec::execute(SmfU
 }
 
 
//------------------------------------------------------------------------------
+// asyncFailure()
+//------------------------------------------------------------------------------
+SmfCampResultT
+SmfCampStateSuspendingExec::asyncFailure(SmfUpgradeCampaign * i_camp)
+{
+       TRACE_ENTER();
+       TRACE("SmfCampStateSuspendingExec::asyncFailure implementation");
+       changeState(i_camp, SmfCampStateErrorDetectedInSuspending::instance());
+       TRACE_LEAVE();
+       return SMF_CAMP_DONE;
+}
+
+//------------------------------------------------------------------------------
 // procResult()
 
//------------------------------------------------------------------------------
 SmfCampResultT 
@@ -1991,6 +2047,18 @@ SmfCampRollingBack::suspend(SmfUpgradeCa
 }
 
 
//------------------------------------------------------------------------------
+// asyncFailure()
+//------------------------------------------------------------------------------
+SmfCampResultT 
+SmfCampRollingBack::asyncFailure(SmfUpgradeCampaign * i_camp)
+{
+       TRACE_ENTER();
+       TRACE("SmfCampRollingBack::asyncFailure implementation");
+
+  return SmfCampRollingBack::suspend(i_camp);
+}
+
+//------------------------------------------------------------------------------
 // procResult()
 
//------------------------------------------------------------------------------
 SmfCampResultT 
diff --git a/src/smf/smfd/SmfCampState.h b/src/smf/smfd/SmfCampState.h
--- a/src/smf/smfd/SmfCampState.h
+++ b/src/smf/smfd/SmfCampState.h
@@ -72,6 +72,8 @@ class SmfCampState {
 
        virtual SmfCampResultT commit(SmfUpgradeCampaign * i_camp);
 
+       virtual SmfCampResultT asyncFailure(SmfUpgradeCampaign * i_camp);
+
        virtual SmfCampResultT procResult(SmfUpgradeCampaign *  i_camp,
                                           SmfUpgradeProcedure * i_procedure,
                                           SmfProcResultT        i_result);
@@ -132,6 +134,8 @@ class SmfCampStateExecuting:public SmfCa
 
        virtual SmfCampResultT suspend(SmfUpgradeCampaign * i_camp);
 
+       virtual SmfCampResultT asyncFailure(SmfUpgradeCampaign * i_camp);
+
        virtual SmfCampResultT procResult(SmfUpgradeCampaign *  i_camp,
                                           SmfUpgradeProcedure * i_procedure,
                                           SmfProcResultT        i_result);
@@ -182,6 +186,8 @@ class SmfCampStateSuspendingExec:public 
 
        virtual SmfCampResultT execute(SmfUpgradeCampaign * i_camp);
 
+       virtual SmfCampResultT asyncFailure(SmfUpgradeCampaign * i_camp);
+
        virtual SmfCampResultT procResult(SmfUpgradeCampaign *  i_camp,
                                           SmfUpgradeProcedure * i_procedure,
                                           SmfProcResultT        i_result);
@@ -345,6 +351,7 @@ class SmfCampRollingBack:public SmfCampS
        virtual SmfCampResultT rollbackSingleMergeProc(SmfUpgradeCampaign * 
i_camp);
        virtual SmfCampResultT rollbackInit(SmfUpgradeCampaign * i_camp);
        virtual SmfCampResultT suspend(SmfUpgradeCampaign * i_camp);
+       virtual SmfCampResultT asyncFailure(SmfUpgradeCampaign * i_camp);
        virtual SmfCampResultT procResult(SmfUpgradeCampaign *  i_camp,
                                           SmfUpgradeProcedure * i_procedure,
                                           SmfProcResultT        i_result);
diff --git a/src/smf/smfd/SmfCampaignThread.cc 
b/src/smf/smfd/SmfCampaignThread.cc
--- a/src/smf/smfd/SmfCampaignThread.cc
+++ b/src/smf/smfd/SmfCampaignThread.cc
@@ -40,6 +40,7 @@
 #include "smf/smfd/smfd_long_dn.h"
 
 SmfCampaignThread *SmfCampaignThread::s_instance = NULL;
+SaNtfSubscriptionIdT SmfCampaignThread::operStateSubId(1);
 
 #define SMF_RDA_RETRY_COUNT 25 /* This is taken as the csi's are assigned in 
parallel */
 
@@ -141,7 +142,12 @@ void SmfCampaignThread::main(NCSCONTEXT 
 SmfCampaignThread::~SmfCampaignThread()
 {
        TRACE_ENTER();
-       SaAisErrorT rc = saNtfFinalize(m_ntfHandle);
+       SaAisErrorT rc(saNtfNotificationUnsubscribe(operStateSubId));
+       if (rc != SA_AIS_OK) {
+               LOG_ER("Failed to unsubscribe to oper state notifications %u", 
rc);
+       }
+
+       rc = saNtfFinalize(m_ntfHandle);
        if (rc != SA_AIS_OK) {
                LOG_ER("Failed to finalize NTF handle %u", rc);
        }
@@ -304,10 +310,14 @@ int SmfCampaignThread::initNtf(void)
 {
        SaAisErrorT rc = SA_AIS_ERR_TRY_AGAIN;
        SaVersionT ntfVersion = { 'A', 1, 1 };
+       SaNtfCallbacksT callbacks = {
+               ntfNotificationCallback,
+               0
+       };
        unsigned int numOfTries = 50;
 
        while (rc == SA_AIS_ERR_TRY_AGAIN && numOfTries > 0) {
-               rc = saNtfInitialize(&m_ntfHandle, NULL, &ntfVersion);
+               rc = saNtfInitialize(&m_ntfHandle, &callbacks, &ntfVersion);
                if (rc != SA_AIS_ERR_TRY_AGAIN) {
                        break;
                }
@@ -320,9 +330,200 @@ int SmfCampaignThread::initNtf(void)
                return -1;
        }
 
+       // subscribe to operational state change notifications generated by AMF
+       rc = initNtfSubscriptions();
+       if (rc != SA_AIS_OK) {
+               LOG_ER("initNtfSubscriptions FAILED rc=%s", saf_error(rc));
+               return -1;
+       }
+
        return 0;
 }
 
+SaAisErrorT SmfCampaignThread::initNtfSubscriptions(void) {
+  TRACE_ENTER();
+  SaAisErrorT rc(SA_AIS_OK);
+
+  do {
+    SaNtfStateChangeNotificationFilterT stateChangeFilter;
+
+    SaAisErrorT rc(saNtfStateChangeNotificationFilterAllocate(
+      m_ntfHandle,
+      &stateChangeFilter,
+      0,
+      0,
+      0,
+      0,
+      0,
+      0));
+
+    if (rc != SA_AIS_OK) {
+      LOG_ER("saNtfAttributeChangeNotificationFilterAllocate FAILED rc=%s",
+             saf_error(rc));
+      break;
+    }
+
+    SaNtfNotificationTypeFilterHandlesT notificationFilterHandles = {
+      0,
+      0,
+      stateChangeFilter.notificationFilterHandle,
+      0,
+      0
+    };
+
+    rc = saNtfNotificationSubscribe(&notificationFilterHandles, 
operStateSubId);
+
+    if (rc != SA_AIS_OK) {
+      LOG_ER("saNtfNotificationSubscribe FAILED rc=%s", saf_error(rc));
+      break;
+    }
+
+    rc = 
saNtfNotificationFilterFree(stateChangeFilter.notificationFilterHandle);
+    if (rc != SA_AIS_OK) {
+      LOG_ER("saNtfNotificationFilterFree FAILED rc=%s", saf_error(rc));
+      break;
+    }
+  } while (false);
+
+  TRACE_LEAVE();
+  return rc;
+}
+
+bool SmfCampaignThread::isAMFOperState(const SaNtfClassIdT& classId) const {
+  TRACE_ENTER();
+  bool status(false);
+
+  if (classId.vendorId == SA_NTF_VENDOR_ID_SAF &&
+      classId.majorId == SA_SVC_AMF &&
+      classId.minorId == SA_AMF_NTFID_SU_OP_STATE) {
+    status = true;
+  }
+
+  TRACE_LEAVE2("%i", status);
+  return status;
+}
+
+void SmfCampaignThread::handleStateChangeNotification(
+  const SaNtfStateChangeNotificationT& stateChangeNotification) {
+  TRACE_ENTER();
+  if (stateChangeNotification.notificationHeader.eventType) {
+    if (*stateChangeNotification.notificationHeader.eventType ==
+          SA_NTF_OBJECT_STATE_CHANGE) {
+      handleObjectStateChangeNotification(stateChangeNotification);
+    } else {
+      TRACE("ignoring state change notification with event type: %i",
+            *stateChangeNotification.notificationHeader.eventType);
+    }
+  }
+  TRACE_LEAVE();
+}
+
+void SmfCampaignThread::handleAmfObjectStateChangeNotification(
+  const SaNtfStateChangeNotificationT& stateChangeNotification) {
+  TRACE_ENTER();
+
+  do {
+    bool disabled(false);
+
+    // see if this is a failure of an upgraded SU
+    for (SaUint16T i(0); i < stateChangeNotification.numStateChanges; i++) {
+      if (stateChangeNotification.changedStates[i].newState ==
+            SA_AMF_OPERATIONAL_DISABLED) {
+        disabled = true;
+        break;
+      }
+    }
+
+    if (!disabled) {
+      TRACE("state change is not to DISABLED -- ignoring");
+      break;
+    }
+
+    for (SaUint16T i(0);
+         i < stateChangeNotification.notificationHeader.numAdditionalInfo;
+         i++) {
+      if (stateChangeNotification.notificationHeader.additionalInfo[i].infoId 
!=
+            SA_AMF_MAINTENANCE_CAMPAIGN_DN ||
+          stateChangeNotification.notificationHeader.additionalInfo[i].infoType
+            != SA_NTF_VALUE_LDAP_NAME) {
+        continue;
+      }
+
+      SaNameT *name(0);
+      SaUint16T dataSize(0);
+
+      SaAisErrorT rc(saNtfPtrValGet(
+        stateChangeNotification.notificationHandle,
+        
&stateChangeNotification.notificationHeader.additionalInfo[i].infoValue,
+        reinterpret_cast<void **>(&name),
+        &dataSize));
+
+      if (rc == SA_AIS_OK) {
+        SaConstStringT maintenanceCampaign(saAisNameBorrow(name));
+
+        if (!strcmp(maintenanceCampaign,
+                    s_instance->m_campaign->getDn().c_str())) {
+          LOG_ER("SU: %s failed after upgrade in campaign",
+                 
saAisNameBorrow(stateChangeNotification.notificationHeader.notificationObject));
+          s_instance->m_campaign->getUpgradeCampaign()->asyncFailure();
+
+          std::string error(saAisNameBorrow(
+            stateChangeNotification.notificationHeader.notificationObject));
+
+          error += " failed after upgrade";
+          s_instance->m_campaign->setError(error);
+        } else {
+          LOG_ER("maintenance campaign received from AMF (%s) is not the "
+                 "same as ours (%s)",
+                 maintenanceCampaign,
+                 s_instance->m_campaign->getDn().c_str());
+        }
+      } else {
+        LOG_ER("saNtfPtrValGet failed: %d", rc);
+      }
+    }
+  } while (false);
+
+  TRACE_LEAVE();
+}
+
+void SmfCampaignThread::handleObjectStateChangeNotification(
+  const SaNtfStateChangeNotificationT& stateChangeNotification) {
+  TRACE_ENTER();
+
+  if (stateChangeNotification.notificationHeader.notificationClassId &&
+      
isAMFOperState(*stateChangeNotification.notificationHeader.notificationClassId))
 {
+    handleAmfObjectStateChangeNotification(stateChangeNotification);
+  } else {
+    TRACE("ignoring non-AMF state change notification");
+  }
+
+  TRACE_LEAVE();
+}
+
+void SmfCampaignThread::ntfNotificationCallback(
+  SaNtfSubscriptionIdT subId,
+  const SaNtfNotificationsT *notification) {
+  TRACE_ENTER();
+
+  do {
+    if (subId != operStateSubId) {
+      TRACE("unknown subscription id received in ntfNotificationCallback: %d",
+            subId);
+      break;
+    }
+
+    if (notification->notificationType == SA_NTF_TYPE_STATE_CHANGE) {
+      s_instance->handleStateChangeNotification(
+        notification->notification.stateChangeNotification);
+    } else {
+      TRACE("ignoring NTF notification of type: %i",
+            notification->notificationType);
+    }
+  } while (false);
+
+  TRACE_LEAVE();
+}
 /** 
  * SmfCampaignThread::send
  * send event to the thread.
@@ -673,18 +874,31 @@ int SmfCampaignThread::handleEvents(void
 {
        TRACE_ENTER();
        NCS_SEL_OBJ mbx_fd = ncs_ipc_get_sel_obj(&m_mbx);
-       struct pollfd fds[1];
+
+       SaSelectionObjectT ntfSelObj(0);
+
+       SaAisErrorT rc(saNtfSelectionObjectGet(m_ntfHandle, &ntfSelObj));
+       if (rc != SA_AIS_OK) {
+               LOG_ER("saNtfSelectionObjectGet FAILED - %s", saf_error(rc));
+               return 1;
+       }
+
+       struct pollfd fds[2];
 
        /* Set up all file descriptors to listen to */
        fds[0].fd = mbx_fd.rmv_obj;
        fds[0].events = POLLIN;
        fds[0].revents = 0;
 
+       fds[1].fd = ntfSelObj;
+       fds[1].events = POLLIN;
+       fds[1].revents = 0;
+
        TRACE("Campaign thread %s waiting for events", 
m_campaign->getDn().c_str());
 
        while (m_running) {
 
-                int ret = poll(fds, 1, SMF_UPDATE_ELAPSED_TIME_INTERVAL);
+               int ret = poll(fds, sizeof(fds) / sizeof(pollfd), 
SMF_UPDATE_ELAPSED_TIME_INTERVAL);
 
                if (ret == -1) {
                        if (errno == EINTR)
@@ -700,7 +914,16 @@ int SmfCampaignThread::handleEvents(void
                        processEvt();
                }
 
-                m_campaign->updateElapsedTime();
+               if (fds[1].revents & POLLIN) {
+                       // dispatch NTF events
+                       rc = saNtfDispatch(m_ntfHandle, SA_DISPATCH_ALL);
+
+                       if (rc != SA_AIS_OK) {
+                               LOG_ER("saNtfDispatch FAILED - %s", 
saf_error(rc));
+                       }
+               }
+
+               m_campaign->updateElapsedTime();
        }
        TRACE_LEAVE();
        return 0;
diff --git a/src/smf/smfd/SmfCampaignThread.h b/src/smf/smfd/SmfCampaignThread.h
--- a/src/smf/smfd/SmfCampaignThread.h
+++ b/src/smf/smfd/SmfCampaignThread.h
@@ -190,9 +190,24 @@ class SmfCampaignThread {
 
        SaAisErrorT createImmHandle(SmfCampaign * i_campaign);
        SaAisErrorT deleteImmHandle();
+  SaAisErrorT initNtfSubscriptions(void);
+
+  void handleStateChangeNotification(const SaNtfStateChangeNotificationT&);
+
+  void handleObjectStateChangeNotification(
+    const SaNtfStateChangeNotificationT&);
+
+  void handleAmfObjectStateChangeNotification(
+    const SaNtfStateChangeNotificationT&);
+
+  bool isAMFOperState(const SaNtfClassIdT&) const;
+
+  static void ntfNotificationCallback(SaNtfSubscriptionIdT,
+                                      const SaNtfNotificationsT *);
 
        static void main(NCSCONTEXT info);
        static SmfCampaignThread *s_instance;
+  static SaNtfSubscriptionIdT operStateSubId;
 
        NCSCONTEXT m_task_hdl;
        SYSF_MBX m_mbx;         /* mailbox */
diff --git a/src/smf/smfd/SmfStepTypes.cc b/src/smf/smfd/SmfStepTypes.cc
--- a/src/smf/smfd/SmfStepTypes.cc
+++ b/src/smf/smfd/SmfStepTypes.cc
@@ -1247,8 +1247,8 @@ SmfStepTypeNodeReboot::execute()
                 return false;
         }
 
-        /* Modify information model and set maintenance status */
-        LOG_NO("STEP: Modify information model and set maintenance status");
+        /* Modify information model */
+        LOG_NO("STEP: Modify information model");
         if (m_step->modifyInformationModel() != SA_AIS_OK) {
                 LOG_ER("Failed to Modify information model in 
step=%s",m_step->getRdn().c_str());
                 return false;
@@ -1261,11 +1261,6 @@ SmfStepTypeNodeReboot::execute()
                 return false;
        }
 
-        if (m_step->setMaintenanceStateActUnits() == false) {
-                LOG_ER("Failed to set maintenance state in 
step=%s",m_step->getRdn().c_str());
-                return false;
-        }
-
         /* The action below is an add on to 
SMF.---------------------------------------*/
         /* See if any of the software bundles installed at online installation 
has the */
         /* saSmfBundleInstallOfflineScope attribute set to 
SA_SMF_CMD_SCOPE_PLM_EE     */
@@ -1372,6 +1367,13 @@ SmfStepTypeNodeReboot::execute()
         /* the units in the same state as before locking                       
          */
         m_step->copyDuInitStateToAu();
 
+        /* Now that the node is up, set the maintenance status */
+        LOG_NO("STEP: Set Maintenance Status");
+        if (m_step->setMaintenanceStateActUnits() == false) {
+                LOG_ER("Failed to set maintenance state in 
step=%s",m_step->getRdn().c_str());
+                return false;
+        }
+
         /* Instantiate activation units */
         LOG_NO("STEP: Instantiate activation units");
         if (m_step->instantiateActivationUnits() == false) {
@@ -1685,8 +1687,8 @@ SmfStepTypeNodeRebootAct::execute()
                 return false;
         }
 
-        /* Modify information model and set maintenance status */
-        LOG_NO("STEP: Modify information model and set maintenance status");
+        /* Modify information model */
+        LOG_NO("STEP: Modify information model");
         if (m_step->modifyInformationModel() != SA_AIS_OK) {
                 LOG_ER("Failed to Modify information model in 
step=%s",m_step->getRdn().c_str());
                 return false;
@@ -1699,11 +1701,6 @@ SmfStepTypeNodeRebootAct::execute()
                 return false;
        }
 
-        if (m_step->setMaintenanceStateActUnits() == false) {
-                LOG_ER("Failed to set maintenance state in 
step=%s",m_step->getRdn().c_str());
-                return false;
-        }
-
         /* Offline installation of new software */
         LOG_NO("STEP: Offline installation of new software");
         if (m_step->offlineInstallNewBundles() == false) {
@@ -1746,6 +1743,13 @@ SmfStepTypeNodeRebootAct::execute()
         /* the units in the same state as before locking                       
          */
         m_step->copyDuInitStateToAu();
 
+        /* Now that the node is up, set the maintenance status */
+        LOG_NO("STEP: Set Maintenance Status");
+        if (m_step->setMaintenanceStateActUnits() == false) {
+                LOG_ER("Failed to set maintenance state in 
step=%s",m_step->getRdn().c_str());
+                return false;
+        }
+
         /* Instantiate activation units */
         LOG_NO("STEP: Instantiate activation units");
         if (m_step->instantiateActivationUnits() == false) {
diff --git a/src/smf/smfd/SmfUpgradeCampaign.cc 
b/src/smf/smfd/SmfUpgradeCampaign.cc
--- a/src/smf/smfd/SmfUpgradeCampaign.cc
+++ b/src/smf/smfd/SmfUpgradeCampaign.cc
@@ -942,6 +942,26 @@ SmfUpgradeCampaign::commit()
 }
 
 
//------------------------------------------------------------------------------
+// asyncFailure()
+//------------------------------------------------------------------------------
+void 
+SmfUpgradeCampaign::asyncFailure()
+{
+       TRACE_ENTER();
+        SmfCampResultT campResult;
+
+        while (1) {
+                campResult = m_state->asyncFailure(this);
+
+                if (campResult != SMF_CAMP_CONTINUE) {
+                        break;
+                }
+        }
+
+       TRACE_LEAVE();
+}
+
+//------------------------------------------------------------------------------
 // procResult()
 
//------------------------------------------------------------------------------
 void 
diff --git a/src/smf/smfd/SmfUpgradeCampaign.h 
b/src/smf/smfd/SmfUpgradeCampaign.h
--- a/src/smf/smfd/SmfUpgradeCampaign.h
+++ b/src/smf/smfd/SmfUpgradeCampaign.h
@@ -354,6 +354,13 @@ void verify();
        void commit();
 
 ///
+/// Purpose: Report Async failure
+/// @param   None.
+/// @return  None.
+///
+       void asyncFailure();
+
+///
 /// Purpose: Procedure result.
 /// @param   None.
 /// @return  None.


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
_______________________________________________
Opensaf-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to