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(¬ificationFilterHandles,
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