ClRcT clCpmShutDown(ClUint32T argc, ClCharT *argv[], ClCharT **retStr) { ClUint32T rc = CL_OK; if (!CL_CPM_IS_ACTIVE()) { cpmCliPrint(retStr, "Node shutdown operation can be performed " "only on CPM/G active"); rc = CL_CPM_RC(CL_ERR_OP_NOT_PERMITTED); goto failure; } if (2 == argc) { ClIocNodeAddressT nodeAddress = 0; nodeAddress = (ClIocNodeAddressT) cpmCliStrToInt(argv[1]); if (nodeAddress <= 0) { cpmCliPrint(retStr, "Invalid node address [%s]", argv[1]); rc = CL_CPM_RC(CL_ERR_INVALID_PARAMETER); goto failure; } rc = clCpmNodeShutDown(nodeAddress); if (CL_OK != rc) { cpmCliPrint(retStr, "Failed to shutdown the node, error [%#x]", rc); goto failure; } } else { rc = CL_CPM_RC(CL_ERR_INVALID_PARAMETER); cpmCliPrint(retStr, "Usage : nodeShutdown <node address>\n" "\tnode address[in decimal] - IOC address " "of the node"); goto failure; } return CL_OK; failure: return rc; }
static void cpmMakeSCActiveOrDeputy(const ClGmsClusterNotificationBufferT *notificationBuffer, ClCpmLocalInfoT *pCpmLocalInfo) { ClUint32T rc = CL_OK; ClGmsNodeIdT prevMasterNodeId = gpClCpm->activeMasterNodeId; ClBoolT leadershipChanged = notificationBuffer->leadershipChanged; /* * Check for initial leadership state incase the cluster track from AMF was issued * after GMS leader election was done and GMS responded back with a track with a leadership changed * set to FALSE for a CURRENT async request from AMF. */ if(leadershipChanged == CL_FALSE && (ClInt32T) notificationBuffer->leader == pCpmLocalInfo->nodeId && (ClInt32T) prevMasterNodeId != pCpmLocalInfo->nodeId && gpClCpm->haState == CL_AMS_HA_STATE_NONE) leadershipChanged = CL_TRUE; if (leadershipChanged == CL_TRUE) { if ( (ClInt32T) notificationBuffer->leader == pCpmLocalInfo->nodeId) { clLogInfo(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_GMS, "Node [%d] has become the leader of the cluster", pCpmLocalInfo->nodeId); if(gpClCpm->haState != CL_AMS_HA_STATE_ACTIVE) { rc = cpmUpdateTL(CL_AMS_HA_STATE_ACTIVE); if (rc != CL_OK) { clLogWrite(CL_LOG_HANDLE_APP, CL_LOG_SEV_DEBUG, NULL, CL_CPM_LOG_1_TL_UPDATE_FAILURE, rc); } } gpClCpm->deputyNodeId = notificationBuffer->deputy; } else if ((ClInt32T) notificationBuffer->deputy == pCpmLocalInfo->nodeId) { clLogInfo(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_GMS, "Node [%d] has become the deputy of the cluster", pCpmLocalInfo->nodeId); /* * Deregister the active registration if going from active to standby. */ if(gpClCpm->haState == CL_AMS_HA_STATE_ACTIVE) { clIocTransparencyDeregister(pCpmLocalInfo->nodeId << CL_CPM_IOC_SLOT_BITS); } rc = cpmUpdateTL(CL_AMS_HA_STATE_STANDBY); if (rc != CL_OK) { clLogWrite(CL_LOG_HANDLE_APP, CL_LOG_SEV_DEBUG, NULL, CL_CPM_LOG_1_TL_UPDATE_FAILURE, rc); } } if ((gpClCpm->haState == CL_AMS_HA_STATE_ACTIVE) && ( (ClInt32T) notificationBuffer->leader != pCpmLocalInfo->nodeId)) { clLogDebug(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_GMS, "Node [%d] is changing HA state from active to standby", pCpmLocalInfo->nodeId); /* * Deregister the entry during a state change. */ if ( (ClInt32T) notificationBuffer->deputy != pCpmLocalInfo->nodeId) { clIocTransparencyDeregister((pCpmLocalInfo->nodeId) << CL_CPM_IOC_SLOT_BITS); } /* * Inform AMS to become standby and read the checkpoint. */ if ((gpClCpm->cpmToAmsCallback != NULL) && (gpClCpm->cpmToAmsCallback->amsStateChange != NULL)) { clLogDebug(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_GMS, "Informing AMS on node [%d] to change state " "from active to standby...", pCpmLocalInfo->nodeId); rc = gpClCpm->cpmToAmsCallback->amsStateChange(CL_AMS_STATE_CHANGE_ACTIVE_TO_STANDBY | CL_AMS_STATE_CHANGE_USE_CHECKPOINT); if (CL_OK != rc) { clLogWarning(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS, "AMS state change from active to standby " "returned [%#x]", rc); } cpmWriteNodeStatToFile("AMS", CL_NO); if(!gClAmsSwitchoverInline) { if (((notificationBuffer->numberOfItems == 0) && (notificationBuffer->notification == NULL)) && gpClCpm->polling && (gpClCpm->nodeLeaving == CL_FALSE)) { /* * This indicates that leader election API of * GMS was called. Since this involves * interaction among only system controllers, * we don't need to restart the worker nodes * like in the case of split brain handling. */ cpmActive2Standby(CL_NO); } else if (( (ClInt32T) notificationBuffer->deputy == pCpmLocalInfo->nodeId) && gpClCpm->polling && (gpClCpm->nodeLeaving == CL_FALSE)) { /* * We try and handle a possible split brain * since presently GMS shouldnt be reelecting. * And even if it does, its pretty much * invalid with respect to AMS where you could * land up with 2 actives. */ /* * We arent expected to return back. */ cpmActive2Standby(CL_NO); } } } /* * Bug 4168: * Updating the data structure gpClCpm, when the active becomes * standby. */ gpClCpm->haState = CL_AMS_HA_STATE_STANDBY; gpClCpm->activeMasterNodeId = notificationBuffer->leader; gpClCpm->deputyNodeId = notificationBuffer->deputy; if(gClAmsSwitchoverInline) { /* *Re-register with active. */ clOsalMutexUnlock(&gpClCpm->clusterMutex); cpmSwitchoverActive(); clOsalMutexLock(&gpClCpm->clusterMutex); } } else if ((gpClCpm->haState == CL_AMS_HA_STATE_STANDBY) && ( (ClInt32T) notificationBuffer->leader == pCpmLocalInfo->nodeId)) { rc = cpmStandby2Active(prevMasterNodeId, notificationBuffer->deputy); if (CL_OK != rc) { return; } } else if ((gpClCpm->haState == CL_AMS_HA_STATE_NONE) && ( (ClInt32T) notificationBuffer->leader == pCpmLocalInfo->nodeId)) { /* * Bug 4411: * Added the if-else block. * Calling the AMS initialize only if both the callback pointers * are not NULL. * FIXME: This change is sort of workaround for 2.2. * Neat solution is to protect gpClCpm structure and fields properly */ if ((gpClCpm->amsToCpmCallback != NULL) && (gpClCpm->cpmToAmsCallback != NULL)) { clLogDebug(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS,"Starting AMS in active mode..."); rc = clAmsStart(&gAms,CL_AMS_INSTANTIATE_MODE_ACTIVE | CL_AMS_INSTANTIATE_USE_CHECKPOINT); /* * Bug 4092: * If the AMS intitialize fails then do the * self shut down. */ if (CL_OK != rc) { clLogCritical(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS,"Unable to initialize AMF, error = [%#x]", rc); gpClCpm->amsToCpmCallback = NULL; cpmReset(NULL,NULL); return; } } else { rc = CL_CPM_RC(CL_ERR_NULL_POINTER); if (!gpClCpm->polling) { clLogCritical(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS, "AMF finalize called before AMF initialize during node shutdown."); } else { clLogCritical(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS, "Unable to initialize AMF, error = [%#x]", rc); cpmRestart(NULL,NULL); } return; } gpClCpm->haState = CL_AMS_HA_STATE_ACTIVE; gpClCpm->activeMasterNodeId = notificationBuffer->leader; gpClCpm->deputyNodeId = notificationBuffer->deputy; } /* * There could be more than 1 standby SC. * Every none HA-state SC except the master is updated to become to standby SC. */ else if (gpClCpm->haState == CL_AMS_HA_STATE_NONE) { /* * Bug 4411: * Added the if-else block. * Calling the clAmsStart only if both the callback pointers * are not NULL. * FIXME: This change is sort of workaround for 2.2. * Neat solution is to protect gpClCpm structure and fields properly */ if ((gpClCpm->amsToCpmCallback != NULL) && (gpClCpm->cpmToAmsCallback != NULL)) { clLogDebug(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS, "Starting AMS in standby mode..."); rc = clAmsStart(&gAms,CL_AMS_INSTANTIATE_MODE_STANDBY); /* * Bug 4092: * If the AMS initialize fails then do the * self shut down. */ if (CL_OK != rc) { clLogCritical(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS,"Unable to initialize AMS, error = [%#x]", rc); gpClCpm->amsToCpmCallback = NULL; cpmRestart(NULL,NULL); return; } } else { rc = CL_CPM_RC(CL_ERR_NULL_POINTER); if (!gpClCpm->polling) { clLogCritical(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS,"AMS finalize called before AMS initialize during node shutdown."); } else { clLogCritical(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS,"Unable to initialize AMS, error = [%#x]", rc); cpmRestart(NULL,NULL); } return; } gpClCpm->haState = CL_AMS_HA_STATE_STANDBY; gpClCpm->activeMasterNodeId = notificationBuffer->leader; gpClCpm->deputyNodeId = notificationBuffer->deputy; if(gpClCpm->bmTable->currentBootLevel == pCpmLocalInfo->defaultBootLevel) { cpmInitializeStandby(); } } else { gpClCpm->activeMasterNodeId = notificationBuffer->leader; gpClCpm->deputyNodeId = notificationBuffer->deputy; } clLogNotice(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_CPM, "HA state of node [%s] with node ID [%d] is [%s], " "Master node is [%d]", pCpmLocalInfo->nodeName, pCpmLocalInfo->nodeId, gpClCpm->haState == CL_AMS_HA_STATE_ACTIVE ? "Active": gpClCpm->haState == CL_AMS_HA_STATE_STANDBY ? "Standby": "None", gpClCpm->activeMasterNodeId); } else { /* * Always update the deputy node ID. It may be that this * path is reached because a deputy node failed. */ gpClCpm->deputyNodeId = notificationBuffer->deputy; if (CL_CPM_IS_ACTIVE()) { if(notificationBuffer->notification && notificationBuffer->numberOfItems == 1) { if (CL_GMS_NODE_LEFT == notificationBuffer->notification->clusterChange) { cpmFailoverNode(notificationBuffer->notification-> clusterNode.nodeId, CL_FALSE); } else { clLogNotice(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS, "Ignoring notification of type [%d] for node [%d]", notificationBuffer->notification->clusterChange, notificationBuffer->notification->clusterNode.nodeId); } } else if(notificationBuffer->notification) { clLogNotice(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS, "Ignoring notification with number of items [%d], first type [%d]", notificationBuffer->numberOfItems, notificationBuffer->notification->clusterChange); } } else if ((gpClCpm->haState == CL_AMS_HA_STATE_NONE) && ( (ClInt32T) notificationBuffer->deputy == pCpmLocalInfo->nodeId)) { if(CL_GMS_NODE_JOINED == notificationBuffer->notification->clusterChange) { cpmStandbyRecover(notificationBuffer); } else if(gpClCpm->bmTable->currentBootLevel == pCpmLocalInfo->defaultBootLevel) { cpmStandbyRecover(notificationBuffer); cpmInitializeStandby(); } } } return ; }