osaf/services/saf/smfsv/config/smfsv_classes.xml     |   21 +
 osaf/services/saf/smfsv/smfd/SmfCampState.cc         |  281 ++++-
 osaf/services/saf/smfsv/smfd/SmfCampState.hh         |    2 +
 osaf/services/saf/smfsv/smfd/SmfCampaign.cc          |  137 +-
 osaf/services/saf/smfsv/smfd/SmfCampaign.hh          |    6 +
 osaf/services/saf/smfsv/smfd/SmfCampaignXmlParser.cc |    2 +-
 osaf/services/saf/smfsv/smfd/SmfProcState.cc         |   25 +-
 osaf/services/saf/smfsv/smfd/SmfStepState.cc         |   21 +-
 osaf/services/saf/smfsv/smfd/SmfTargetTemplate.hh    |   20 +
 osaf/services/saf/smfsv/smfd/SmfUpgradeAction.cc     |    8 +
 osaf/services/saf/smfsv/smfd/SmfUpgradeAction.hh     |    3 +
 osaf/services/saf/smfsv/smfd/SmfUpgradeCampaign.cc   |   22 +-
 osaf/services/saf/smfsv/smfd/SmfUpgradeCampaign.hh   |   26 +
 osaf/services/saf/smfsv/smfd/SmfUpgradeMethod.hh     |    4 +-
 osaf/services/saf/smfsv/smfd/SmfUpgradeProcedure.cc  |  987 ++++++++++++++++++-
 osaf/services/saf/smfsv/smfd/SmfUpgradeProcedure.hh  |  135 ++
 osaf/services/saf/smfsv/smfd/SmfUpgradeStep.cc       |   31 +-
 osaf/services/saf/smfsv/smfd/SmfUpgradeStep.hh       |   56 +-
 osaf/services/saf/smfsv/smfd/SmfUtils.cc             |   15 +
 osaf/services/saf/smfsv/smfd/SmfUtils.hh             |    3 +
 osaf/services/saf/smfsv/smfd/smfd.h                  |    6 +
 osaf/services/saf/smfsv/smfd/smfd_campaign_oi.cc     |   59 +-
 osaf/services/saf/smfsv/smfd/smfd_cb.h               |    6 +
 23 files changed, 1707 insertions(+), 169 deletions(-)


smfd can be configured to merge all procedures in a campaign
into a single step procedure before execution.
Prerequisite: Procedures shall not have any ordering dependencies.

diff --git a/osaf/services/saf/smfsv/config/smfsv_classes.xml 
b/osaf/services/saf/smfsv/config/smfsv_classes.xml
--- a/osaf/services/saf/smfsv/config/smfsv_classes.xml
+++ b/osaf/services/saf/smfsv/config/smfsv_classes.xml
@@ -392,6 +392,12 @@
                         <flag>SA_WRITABLE</flag>
                         <default-value>0</default-value>
                </attr>
+               <attr>
+                       <name>openSafSmfExecControl</name>
+                       <type>SA_STRING_T</type>
+                       <category>SA_CONFIG</category>
+                       <flag>SA_WRITABLE</flag>
+               </attr>
        </class>
        <class name="OpenSafSmfCampRestartInfo">
                <category>SA_RUNTIME</category>
@@ -511,4 +517,19 @@
                        <flag>SA_WRITABLE</flag>
                </attr>
        </class>
+       <class name="OpenSafSmfExecControl">
+               <category>SA_CONFIG</category>
+               <rdn>
+                       <name>openSafSmfExecControl</name>
+                       <type>SA_STRING_T</type>
+                       <category>SA_CONFIG</category>
+               </rdn>
+               <attr>
+                       <name>procExecMode</name>
+                       <type>SA_UINT32_T</type>
+                       <category>SA_CONFIG</category>
+                       <flag>SA_WRITABLE</flag>
+                       <default-value>0</default-value>
+               </attr>
+       </class>
 </imm:IMM-contents>
diff --git a/osaf/services/saf/smfsv/smfd/SmfCampState.cc 
b/osaf/services/saf/smfsv/smfd/SmfCampState.cc
--- a/osaf/services/saf/smfsv/smfd/SmfCampState.cc
+++ b/osaf/services/saf/smfsv/smfd/SmfCampState.cc
@@ -117,6 +117,18 @@ SmfCampState::rollbackProc(SmfUpgradeCam
 }
 
 
//------------------------------------------------------------------------------
+// rollbackSingleMergeProc()
+//------------------------------------------------------------------------------
+SmfCampResultT 
+SmfCampState::rollbackSingleMergeProc(SmfUpgradeCampaign * i_camp)
+{
+       TRACE_ENTER();
+       LOG_ER("SmfCampState::rollbackSingleMergeProc default implementation, 
should NEVER be executed.");
+       TRACE_LEAVE();
+        return SMF_CAMP_DONE;
+}
+
+//------------------------------------------------------------------------------
 // rollback()
 
//------------------------------------------------------------------------------
 SmfCampResultT 
@@ -318,7 +330,25 @@ SmfCampStateInitial::execute(SmfUpgradeC
        //Preparation is ready, change state and execute campaign initialization
        changeState(i_camp, SmfCampStateExecuting::instance());
 
-    initResult = executeInit(i_camp);
+        initResult = executeInit(i_camp);
+        if (initResult != SMF_CAMP_FAILED) {
+               //If the campaign init portion contain changes to SMF config 
there may be
+               //a race condition between the smfd main process (OI) which set 
the smfd_cb
+               //and this thread executing right here (the campaign) when 
reading the same smfd_cb.
+               //To be sure the smfd_cb is updated also for this thread, read 
the config again.
+               read_config_and_set_control_block(smfd_cb);
+
+               //Save the smfd_cb->procExecutionMode in the campaign. If 
configuration
+               //is altered after the <campaignInitilatization> portion it 
shall not 
+               //affect the running campaign.
+               i_camp->setProcExecutionMode(smfd_cb->procExecutionMode);
+
+               LOG_NO("SmfCampStateInitial::execute: startProcedureThreads()");
+                if 
(SmfCampaignThread::instance()->campaign()->startProcedureThreads() != 
SA_AIS_OK) {
+                        LOG_NO("Fail to start procedure threads");
+                        initResult = SMF_CAMP_FAILED;
+                }
+        }
        TRACE_LEAVE();
        return initResult;
 
@@ -683,7 +713,6 @@ exit_error:
        return SA_AIS_ERR_FAILED_OPERATION;
 }
 
-
 
//------------------------------------------------------------------------------
 
//------------------------------------------------------------------------------
 // SmfCampStateExecuting implementations
@@ -728,11 +757,21 @@ SmfCampStateExecuting::execute(SmfUpgrad
 
        TRACE("SmfCampStateExecuting::execute, Do some checking");
 
+       //Set the ProcExecutionMode in restarted campaign
+       i_camp->setProcExecutionMode(smfd_cb->procExecutionMode);
+
        //If a running campaign was restarted on another node, the procedures 
in executing state
        //must be restarted. The execution shall continue at step execution 
phase. The procedure initialization
        //and step calculation was performed before the move of control.
-        const std::vector < SmfUpgradeProcedure * >& procedures = 
i_camp->getProcedures();
-        std::vector < SmfUpgradeProcedure * >::const_iterator iter;
+
+        std::vector < SmfUpgradeProcedure * > procedures;
+        if (i_camp->getProcExecutionMode() == SMF_MERGE_TO_SINGLE_STEP) {
+                procedures.push_back(i_camp->getMergedProc());
+        } else {
+                procedures = i_camp->getProcedures();
+        }
+
+        std::vector < SmfUpgradeProcedure * >::iterator iter;
        bool execProcFound = false;
 
        iter = procedures.begin();
@@ -758,8 +797,9 @@ SmfCampStateExecuting::execute(SmfUpgrad
                return SMF_CAMP_DONE;
        }
 
-       /* No executing procedures, start executing next procedure */
+        /* No executing procedures, start executing next procedure */
         SmfCampResultT result = this->executeProc(i_camp);
+
         TRACE_LEAVE();
         return result;
 }
@@ -777,8 +817,14 @@ SmfCampStateExecuting::executeProc(SmfUp
        //The procedure vector is sorted in execution level order (low -> high)
        //Lowest number shall be executed first.
 
-        const std::vector < SmfUpgradeProcedure * >& procedures = 
i_camp->getProcedures();
-       std::vector < SmfUpgradeProcedure * >::const_iterator iter;
+        std::vector < SmfUpgradeProcedure * > procedures;
+        if (i_camp->getProcExecutionMode() == SMF_MERGE_TO_SINGLE_STEP) {
+                procedures.push_back(i_camp->getMergedProc());
+        } else {
+                procedures = i_camp->getProcedures();
+        }
+
+       std::vector < SmfUpgradeProcedure * >::iterator iter;
        int execLevel = -1;
 
        iter = procedures.begin();
@@ -866,8 +912,14 @@ SmfCampStateExecuting::suspend(SmfUpgrad
        TRACE("SmfCampStateExecuting::suspend implementation");
 
        /* Send suspend message to all procedures */
-        const std::vector < SmfUpgradeProcedure * >& procedures = 
i_camp->getProcedures();
-       std::vector < SmfUpgradeProcedure * >::const_iterator iter;
+        std::vector < SmfUpgradeProcedure * > procedures;
+        if (i_camp->getProcExecutionMode() == SMF_MERGE_TO_SINGLE_STEP) {
+                procedures.push_back(i_camp->getMergedProc());
+        } else {
+                procedures = i_camp->getProcedures();
+        }
+
+       std::vector < SmfUpgradeProcedure * >::iterator iter;
 
        for (iter = procedures.begin(); iter != procedures.end(); ++iter) {
                 TRACE("SmfCampStateExecuting::Procedure %s, send suspend",
@@ -914,9 +966,14 @@ SmfCampStateExecuting::procResult(SmfUpg
                 LOG_NO("CAMP: Procedure %s returned STEPUNDONE", 
i_procedure->getProcName().c_str());
 
                 /* Send suspend message to all procedures */
-                const std::vector < SmfUpgradeProcedure * >& procedures = 
i_camp->getProcedures();
-               std::vector < SmfUpgradeProcedure * >::const_iterator iter;
-        
+                std::vector < SmfUpgradeProcedure * > procedures;
+                if (i_camp->getProcExecutionMode() == 
SMF_MERGE_TO_SINGLE_STEP) {
+                        procedures.push_back(i_camp->getMergedProc());
+                } else {
+                        procedures = i_camp->getProcedures();
+                }
+
+               std::vector < SmfUpgradeProcedure * >::iterator iter;
                for (iter = procedures.begin(); iter != procedures.end(); 
++iter) {
                         TRACE("SmfCampStateExecuting:: Step undone, send 
suspend to procedure %s",
                               (*iter)->getProcName().c_str());
@@ -935,7 +992,7 @@ SmfCampStateExecuting::procResult(SmfUpg
         }
         default: {
                 LOG_NO("SmfCampStateExecuting::procResult received unhandled 
response %d from procedure %s", 
-                       i_result, i_procedure->getDn().c_str());                
+                       i_result, i_procedure->getDn().c_str());
                 break;
         }
         }
@@ -955,6 +1012,7 @@ SmfCampStateExecuting::procResult(SmfUpg
 
         /* Find next procedure to be executed */
         SmfCampResultT result = this->executeProc(i_camp);
+
         TRACE_LEAVE();
         return result;
 }
@@ -1055,13 +1113,23 @@ SmfCampStateExecCompleted::commit(SmfUpg
 
         i_camp->resetMaintenanceState(); // No action if it fails
 
-       //Remove the procedure runtime objects
-        const std::vector < SmfUpgradeProcedure * >& procedures = 
i_camp->getProcedures();
-       std::vector < SmfUpgradeProcedure * >::const_iterator iter;
+        //Remove the procedure runtime objects
+       if (i_camp->getProcExecutionMode() == SMF_MERGE_TO_SINGLE_STEP) {
+                i_camp->getMergedProc()->commit();
 
-        for (iter = procedures.begin(); iter != procedures.end(); ++iter) {
-               (*iter)->commit();
-       }
+        } else {
+               std::vector < SmfUpgradeProcedure * > procedures;
+               if (i_camp->getProcExecutionMode() == SMF_MERGE_TO_SINGLE_STEP) 
{
+                       procedures.push_back(i_camp->getMergedProc());
+               } else {
+                       procedures = i_camp->getProcedures();
+               }
+
+                std::vector < SmfUpgradeProcedure * >::iterator iter;
+                for (iter = procedures.begin(); iter != procedures.end(); 
++iter) {
+                        (*iter)->commit();
+                }
+        }
 
         i_camp->removeRunTimeObjects(); // No action if it fails
        i_camp->removeConfigObjects();  // No action if it fails
@@ -1140,8 +1208,19 @@ SmfCampStateSuspendingExec::execute(SmfU
         */
        TRACE_ENTER();
        TRACE("SmfCampStateSuspendingExec::execute implementation");
-       const std::vector < SmfUpgradeProcedure * >& procedures = 
i_camp->getProcedures();
-       std::vector < SmfUpgradeProcedure * >::const_iterator iter;
+
+       //Set the ProcExecutionMode in case campaign was restarted 
+       //in while in SuspendingExec state
+       i_camp->setProcExecutionMode(smfd_cb->procExecutionMode);
+
+        std::vector < SmfUpgradeProcedure * > procedures;
+        if (i_camp->getProcExecutionMode() == SMF_MERGE_TO_SINGLE_STEP) {
+                procedures.push_back(i_camp->getMergedProc());
+        } else {
+                procedures = i_camp->getProcedures();
+        }
+
+       std::vector < SmfUpgradeProcedure * >::iterator iter;
        bool initialFound = false;
 
        // Searching if any procedure is in initial status.
@@ -1191,12 +1270,16 @@ SmfCampStateSuspendingExec::procResult(S
         case SMF_PROC_SUSPENDED: {
                 /* If first response, set number of expected responses */
                 if (i_camp->m_noOfProcResponses == 0) {
-                        i_camp->m_noOfProcResponses = 
i_camp->getProcedures().size();
+                        if (i_camp->getProcExecutionMode() == 
SMF_MERGE_TO_SINGLE_STEP) {
+                                i_camp->m_noOfProcResponses = 1;
+                        } else {
+                                i_camp->m_noOfProcResponses = 
i_camp->getProcedures().size();
+                        }
                 }
 
                 /* Decrease the response counter */
                 i_camp->m_noOfProcResponses--;
-        
+
                 /* If last response, change state to suspended */
                 if (i_camp->m_noOfProcResponses == 0) {
                        changeState(i_camp, 
SmfCampStateExecSuspended::instance());
@@ -1270,9 +1353,19 @@ SmfCampStateExecSuspended::execute(SmfUp
        TRACE_ENTER();
        TRACE("SmfCampStateExecSuspended::execute implementation");
 
+       //Set the ProcExecutionMode in case campaign was restarted 
+       //in while in suspended state
+       i_camp->setProcExecutionMode(smfd_cb->procExecutionMode);
+
        /* Send execute to all suspended procedures */
-        const std::vector < SmfUpgradeProcedure * >& procedures = 
i_camp->getProcedures();
-       std::vector < SmfUpgradeProcedure * >::const_iterator iter;
+        std::vector < SmfUpgradeProcedure * > procedures;
+        if (i_camp->getProcExecutionMode() == SMF_MERGE_TO_SINGLE_STEP) {
+                procedures.push_back(i_camp->getMergedProc());
+        } else {
+                procedures = i_camp->getProcedures();
+        }
+
+       std::vector < SmfUpgradeProcedure * >::iterator iter;
 
        changeState(i_camp, SmfCampStateExecuting::instance());
         for (iter = procedures.begin(); iter != procedures.end(); ++iter) {
@@ -1328,10 +1421,16 @@ SmfCampStateExecSuspended::rollback(SmfU
                changeState(i_camp, SmfCampRollbackFailed::instance());
                return SMF_CAMP_FAILED;
        }
-       
+
        /* Send rollback to all suspended procedures */
-        const std::vector < SmfUpgradeProcedure * >& procedures = 
i_camp->getProcedures();
-       std::vector < SmfUpgradeProcedure * >::const_iterator iter;
+        std::vector < SmfUpgradeProcedure * > procedures;
+        if (i_camp->getProcExecutionMode() == SMF_MERGE_TO_SINGLE_STEP) {
+                procedures.push_back(i_camp->getMergedProc());
+        } else {
+                procedures = i_camp->getProcedures();
+        }
+
+       std::vector < SmfUpgradeProcedure * >::iterator iter;
 
        for (iter = procedures.begin(); iter != procedures.end(); ++iter) {
                switch ((*iter)->getState()) {
@@ -1624,9 +1723,19 @@ SmfCampStateSuspendedByErrorDetected::ex
        TRACE_ENTER();
        TRACE("SmfCampStateSuspendedByErrorDetected::execute implementation");
 
+       //Set the ProcExecutionMode in case campaign was restarted 
+       //in while in suspendedByErrorDetected state
+       i_camp->setProcExecutionMode(smfd_cb->procExecutionMode);
+
        /* Send execute to all suspended/undone procedures */
-        const std::vector < SmfUpgradeProcedure * >& procedures = 
i_camp->getProcedures();
-       std::vector < SmfUpgradeProcedure * >::const_iterator iter;
+        std::vector < SmfUpgradeProcedure * > procedures;
+        if (i_camp->getProcExecutionMode() == SMF_MERGE_TO_SINGLE_STEP) {
+                procedures.push_back(i_camp->getMergedProc());
+        } else {
+                procedures = i_camp->getProcedures();
+        }
+
+       std::vector < SmfUpgradeProcedure * >::iterator iter;
 
        changeState(i_camp, SmfCampStateExecuting::instance());
        for (iter = procedures.begin(); iter != procedures.end(); ++iter) {
@@ -1678,10 +1787,16 @@ SmfCampStateSuspendedByErrorDetected::ro
                changeState(i_camp, SmfCampRollbackFailed::instance());
                return SMF_CAMP_FAILED;
        }
-       
+
        /* Send rollback to all suspended/undone procedures */
-        const std::vector < SmfUpgradeProcedure * >& procedures = 
i_camp->getProcedures();
-       std::vector < SmfUpgradeProcedure * >::const_iterator iter;
+        std::vector < SmfUpgradeProcedure * > procedures;
+        if (i_camp->getProcExecutionMode() == SMF_MERGE_TO_SINGLE_STEP) {
+                procedures.push_back(i_camp->getMergedProc());
+        } else {
+                procedures = i_camp->getProcedures();
+        }
+
+       std::vector < SmfUpgradeProcedure * >::iterator iter;
 
        for (iter = procedures.begin(); iter != procedures.end(); ++iter) {
                switch ((*iter)->getState()) {
@@ -1758,8 +1873,14 @@ SmfCampRollingBack::rollback(SmfUpgradeC
        TRACE_ENTER();
        TRACE("SmfCampRollingBack::rollback implementation");
 
-        const std::vector < SmfUpgradeProcedure * >& procedures = 
i_camp->getProcedures();
-       std::vector < SmfUpgradeProcedure * >::const_reverse_iterator iter;
+        std::vector < SmfUpgradeProcedure * > procedures;
+        if (i_camp->getProcExecutionMode() == SMF_MERGE_TO_SINGLE_STEP) {
+                procedures.push_back(i_camp->getMergedProc());
+        } else {
+                procedures = i_camp->getProcedures();
+        }
+
+       std::vector < SmfUpgradeProcedure * >::reverse_iterator iter;
 
        //If a running campaign was restarted on an other node, the procedures 
in rolling back state
        //must be restarted. The execution shall continue at step rollback 
phase. 
@@ -1786,8 +1907,13 @@ SmfCampRollingBack::rollback(SmfUpgradeC
                return SMF_CAMP_DONE;
        }
 
-        /* No running procedures, continue with next procedure */
-        SmfCampResultT procResult = rollbackProc(i_camp);
+        SmfCampResultT procResult;
+        if (i_camp->getProcExecutionMode() == SMF_MERGE_TO_SINGLE_STEP) {
+                procResult = this->rollbackSingleMergeProc(i_camp);
+        } else {
+                /* No running procedures, continue with next procedure */
+                procResult = rollbackProc(i_camp);
+        }
        TRACE_LEAVE();
         return procResult;
 }
@@ -1834,8 +1960,14 @@ SmfCampRollingBack::rollbackProc(SmfUpgr
        //The procedure vector is sorted in execution level order (low -> high)
        //Highest number shall be rolled back first so start from end of list.
 
-        const std::vector < SmfUpgradeProcedure * >& procedures = 
i_camp->getProcedures();
-       std::vector < SmfUpgradeProcedure * >::const_reverse_iterator iter;
+        std::vector < SmfUpgradeProcedure * > procedures;
+        if (i_camp->getProcExecutionMode() == SMF_MERGE_TO_SINGLE_STEP) {
+                procedures.push_back(i_camp->getMergedProc());
+        } else {
+                procedures = i_camp->getProcedures();
+        }
+
+       std::vector < SmfUpgradeProcedure * >::reverse_iterator iter;
 
         int execLevel = -1;
        
@@ -1878,6 +2010,33 @@ SmfCampRollingBack::rollbackProc(SmfUpgr
 }
 
 
//------------------------------------------------------------------------------
+// rollbackSingleMergeProc()
+//------------------------------------------------------------------------------
+SmfCampResultT 
+SmfCampRollingBack::rollbackSingleMergeProc(SmfUpgradeCampaign * i_camp)
+{
+       TRACE_ENTER();
+       LOG_NO("CAMP:: Rollback merged single step procedure only");
+        SmfUpgradeProcedure * mergedProc = i_camp->getMergedProc();
+        if (mergedProc->getState() == SA_SMF_PROC_COMPLETED) {
+                SmfProcedureThread *procThread = mergedProc->getProcThread();
+                PROCEDURE_EVT *evt = new PROCEDURE_EVT();
+                evt->type = PROCEDURE_EVT_ROLLBACK;
+                procThread->send(evt);
+
+                TRACE("SmfCampRollingBack::rollbackSingleMergeProc, Wait for 
procedure result");
+               TRACE_LEAVE();
+               return SMF_CAMP_DONE;
+        }
+
+       LOG_NO("CAMP: The single step merge procedure is rolled back, start 
rollback of init");
+        SmfCampResultT result = this->rollbackInit(i_camp);
+
+        TRACE_LEAVE();
+        return result;
+}
+
+//------------------------------------------------------------------------------
 // suspend()
 
//------------------------------------------------------------------------------
 SmfCampResultT 
@@ -1887,8 +2046,14 @@ SmfCampRollingBack::suspend(SmfUpgradeCa
        TRACE("SmfCampRollingBack::suspend implementation");
 
        /* Send suspend message to all procedures */
-        const std::vector < SmfUpgradeProcedure * >& procedures = 
i_camp->getProcedures();
-       std::vector < SmfUpgradeProcedure * >::const_iterator iter;
+        std::vector < SmfUpgradeProcedure * > procedures;
+        if (i_camp->getProcExecutionMode() == SMF_MERGE_TO_SINGLE_STEP) {
+          procedures.push_back(i_camp->getMergedProc());
+        } else {
+          procedures = i_camp->getProcedures();
+        }
+
+       std::vector < SmfUpgradeProcedure * >::iterator iter;
 
         changeState(i_camp, SmfCampSuspendingRollback::instance());
         for (iter = procedures.begin(); iter != procedures.end(); ++iter) {
@@ -1951,8 +2116,13 @@ SmfCampRollingBack::procResult(SmfUpgrad
 
        TRACE("All procedures rolled back on the same execlevel have 
answered.");
 
-        /* Find next procedure to be rolled back */
-        SmfCampResultT result = this->rollbackProc(i_camp);
+        SmfCampResultT result;
+        if (i_camp->getProcExecutionMode() == SMF_MERGE_TO_SINGLE_STEP) {
+                result = this->rollbackSingleMergeProc(i_camp);
+        } else {
+                /* Find next procedure to be rolled back */
+                result = this->rollbackProc(i_camp);
+        }
         TRACE_LEAVE();
         return result;
 }
@@ -2002,8 +2172,14 @@ SmfCampRollbackSuspended::rollback(SmfUp
        TRACE("SmfCampRollbackSuspended::rollback implementation");
 
        /* Send rollback to all suspended procedures */
-        const std::vector < SmfUpgradeProcedure * >& procedures = 
i_camp->getProcedures();
-       std::vector < SmfUpgradeProcedure * >::const_iterator iter;
+        std::vector < SmfUpgradeProcedure * > procedures;
+        if (i_camp->getProcExecutionMode() == SMF_MERGE_TO_SINGLE_STEP) {
+          procedures.push_back(i_camp->getMergedProc());
+        } else {
+          procedures = i_camp->getProcedures();
+        }
+
+       std::vector < SmfUpgradeProcedure * >::iterator iter;
 
        changeState(i_camp, SmfCampRollingBack::instance());
        for (iter = procedures.begin(); iter != procedures.end(); ++iter) {
@@ -2169,13 +2345,18 @@ SmfCampRollbackCompleted::commit(SmfUpgr
         i_camp->resetMaintenanceState(); // No action if it fails
 
         //Remove the procedure runtime objects
-        const std::vector < SmfUpgradeProcedure * >& procedures = 
i_camp->getProcedures();
-       std::vector < SmfUpgradeProcedure * >::const_iterator iter;
+        if (i_camp->getProcExecutionMode() == SMF_MERGE_TO_SINGLE_STEP) {
+                i_camp->getMergedProc()->commit();
 
-        for (iter = procedures.begin(); iter != procedures.end(); ++iter) {
-               (*iter)->commit();
-       }
+        } else {
+                const std::vector < SmfUpgradeProcedure * >& procedures = 
i_camp->getProcedures();
+                std::vector < SmfUpgradeProcedure * >::const_iterator iter;
 
+                for (iter = procedures.begin(); iter != procedures.end(); 
++iter) {
+                        (*iter)->commit();
+                }
+        }
+        
         i_camp->removeRunTimeObjects(); // No action if it fails
 
        changeState(i_camp, SmfCampRollbackCommitted::instance());
diff --git a/osaf/services/saf/smfsv/smfd/SmfCampState.hh 
b/osaf/services/saf/smfsv/smfd/SmfCampState.hh
--- a/osaf/services/saf/smfsv/smfd/SmfCampState.hh
+++ b/osaf/services/saf/smfsv/smfd/SmfCampState.hh
@@ -60,6 +60,7 @@ class SmfCampState {
        virtual SmfCampResultT executeProc(SmfUpgradeCampaign * i_camp);
 
        virtual SmfCampResultT rollbackProc(SmfUpgradeCampaign * i_camp);
+       virtual SmfCampResultT rollbackSingleMergeProc(SmfUpgradeCampaign * 
i_camp);
 
        virtual SmfCampResultT rollback(SmfUpgradeCampaign * i_camp);
 
@@ -341,6 +342,7 @@ class SmfCampRollingBack:public SmfCampS
 
        virtual SmfCampResultT rollback(SmfUpgradeCampaign * i_camp);
        virtual SmfCampResultT rollbackProc(SmfUpgradeCampaign * i_camp);
+       virtual SmfCampResultT rollbackSingleMergeProc(SmfUpgradeCampaign * 
i_camp);
        virtual SmfCampResultT rollbackInit(SmfUpgradeCampaign * i_camp);
        virtual SmfCampResultT suspend(SmfUpgradeCampaign * i_camp);
        virtual SmfCampResultT procResult(SmfUpgradeCampaign *  i_camp,
diff --git a/osaf/services/saf/smfsv/smfd/SmfCampaign.cc 
b/osaf/services/saf/smfsv/smfd/SmfCampaign.cc
--- a/osaf/services/saf/smfsv/smfd/SmfCampaign.cc
+++ b/osaf/services/saf/smfsv/smfd/SmfCampaign.cc
@@ -28,6 +28,7 @@
 #include "SmfCampaignXmlParser.hh"
 #include "SmfUpgradeCampaign.hh"
 #include "SmfUpgradeProcedure.hh"
+#include "SmfUpgradeMethod.hh"
 #include "SmfProcedureThread.hh"
 #include "SmfUtils.hh"
 
@@ -37,10 +38,6 @@
 #include <saf_error.h>
 #include "osaf_extended_name.h"
 
-/* We need some DN space for the step (~15),activation/deactivation (~30)
-   and image node (~15) objects */
-#define OSAF_STEP_ACT_LENGTH 60
-
 /*====================================================================*/
 /*  Class SmfCampaign                                                 */
 /*====================================================================*/
@@ -647,47 +644,9 @@ SmfCampaign::initExecution(void)
                         
setExpectedTime((SaTimeT)strtoll(p_uc->getCampaignPeriod().c_str(), NULL, 0));
                 }
 
-                const std::vector < SmfUpgradeProcedure * >& procedures = 
p_uc->getProcedures();
-               std::vector < SmfUpgradeProcedure * >::const_iterator iter;
-        
-               //Set DN and start procedure threads
-               TRACE("SmfCampaign::initExecution, start procedure threads");
-               iter = procedures.begin();
-               while (iter != procedures.end()) {
-                       //Set the DN of the procedure
-                       std::string dn = (*iter)->getProcName() + "," + 
SmfCampaignThread::instance()->campaign()->getDn();
-                        if (dn.length() > 
static_cast<size_t>(smfd_cb->maxDnLength - OSAF_STEP_ACT_LENGTH)) {
-                                std::string error = "Procedure dn too long " + 
dn;
-                                LOG_ER("Procedure dn too long (max %zu) %s",
-                                       
static_cast<size_t>(smfd_cb->maxDnLength - OSAF_STEP_ACT_LENGTH),
-                                       dn.c_str());
-                                setError(error);
-                                delete p_uc; // To terminate and remove any 
previously started procedure threads
-                                /* Don't change campaign state to allow 
reexecution */
-                                return SA_AIS_OK;
-                        }
-                       (*iter)->setDn(dn);
-
-                        /* Start procedure thread */
-                        SmfProcedureThread *procThread = new 
SmfProcedureThread(*iter);
-                        /* The procThread will set itself when started 
correctly */
-                       (*iter)->setProcThread(NULL);
-        
-                       TRACE("SmfCampaign::initExecution, Starting procedure 
thread %s", (*iter)->getProcName().c_str());
-                       procThread->start();
-
-                        /* Check if procedure thread started correctly */
-                        if ((*iter)->getProcThread() == NULL) {
-                                std::string error = "Start of procedure thread 
failed for " + dn;
-                                LOG_ER("%s", error.c_str());
-                                setError(error);
-                                delete p_uc; // To terminate and remove any 
previously started procedure threads
-                                /* Don't change campaign state to allow 
reexecution */
-                                return SA_AIS_OK;
-                        }
-        
-                       iter++;
-               }
+                //Procedure thread start moved from here. They are now started:
+                // 1) if new campaign, after campaign init actions 
(SmfCampStateInitial::execute)
+                // 2) if ongoiong campaign when execution is continued 
(SmfUpgradeCampaign::continueExec)
 
                 /* Indicate that campaign execution is possible */
                setUpgradeCampaign(p_uc);
@@ -696,6 +655,94 @@ SmfCampaign::initExecution(void)
        return SA_AIS_OK;
 }
 
+//------------------------------------------------------------------------------
+// startProcedureThreads()
+//------------------------------------------------------------------------------
+SaAisErrorT
+SmfCampaign::startProcedureThreads()
+{
+        TRACE_ENTER();
+        SmfUpgradeCampaign *p_uc = getUpgradeCampaign();
+        if (p_uc->getProcExecutionMode() == SMF_MERGE_TO_SINGLE_STEP) {
+                SmfUpgradeProcedure *singleProc = new(std::nothrow) 
SmfUpgradeProcedure;
+                osafassert(singleProc != NULL);
+                //Mark it as a merged procedure
+                singleProc->setIsMergedProcedure(true);
+                //Make it a single step procedure
+                SmfSinglestepUpgrade *su = new(std::nothrow) 
SmfSinglestepUpgrade;
+                singleProc->setUpgradeMethod(su);
+                //Set procedure name
+                singleProc->setProcName(SMF_MERGED_SS_PROC_NAME);
+                std::string singleProcDN = singleProc->getProcName() + "," +
+                        SmfCampaignThread::instance()->campaign()->getDn();
+                singleProc->setDn(singleProcDN);
+                p_uc->setMergedProc(singleProc);
+
+                /* Start procedure thread */
+                SmfProcedureThread *procThread = new 
SmfProcedureThread(singleProc);
+                /* The procThread will set itself when started correctly */
+                singleProc->setProcThread(NULL);
+
+                LOG_NO("SmfCampaign::startProcedureThreads, Starting procedure 
thread %s",
+                       singleProc->getProcName().c_str());
+                procThread->start();
+                /* Check if procedure thread started correctly */
+                if (singleProc->getProcThread() == NULL) {
+                        std::string error = "Start of procedure thread failed 
for " + singleProcDN;
+                        LOG_ER("%s", error.c_str());
+                        
SmfCampaignThread::instance()->campaign()->setError(error);
+                        delete p_uc; // To terminate and remove any previously 
started procedure threads
+                        /* Don't change campaign state to allow reexecution */
+                        return SA_AIS_OK;
+                }
+        } else {
+                const std::vector < SmfUpgradeProcedure * >& procedures = 
p_uc->getProcedures();
+                std::vector < SmfUpgradeProcedure * >::const_iterator iter;
+
+                //Set DN and start procedure threads
+                TRACE("SmfCampaign::startProcedureThreads, start procedure 
threads. No proc=[%lu]",
+                      procedures.size());
+                iter = procedures.begin();
+                while (iter != procedures.end()) {
+                        //Set the DN of the procedure
+                        std::string dn = (*iter)->getProcName() + "," + 
SmfCampaignThread::instance()->campaign()->getDn();
+                        if (dn.length() > 
static_cast<size_t>(smfd_cb->maxDnLength - OSAF_STEP_ACT_LENGTH)) {
+                                std::string error = "Procedure dn too long " + 
dn;
+                                LOG_ER("Procedure dn too long (max %zu) %s",
+                                       
static_cast<size_t>(smfd_cb->maxDnLength - OSAF_STEP_ACT_LENGTH),
+                                       dn.c_str());
+                                
SmfCampaignThread::instance()->campaign()->setError(error);
+                                delete p_uc; // To terminate and remove any 
previously started procedure threads
+                                /* Don't change campaign state to allow 
reexecution */
+                                return SA_AIS_OK;
+                        }
+                        (*iter)->setDn(dn);
+
+                        /* Start procedure thread */
+                        SmfProcedureThread *procThread = new 
SmfProcedureThread(*iter);
+                        /* The procThread will set itself when started 
correctly */
+                        (*iter)->setProcThread(NULL);
+
+                        TRACE("SmfCampaign::startProcedureThreads, Starting 
procedure thread %s", (*iter)->getProcName().c_str());
+                        procThread->start();
+
+                        /* Check if procedure thread started correctly */
+                        if ((*iter)->getProcThread() == NULL) {
+                                std::string error = "Start of procedure thread 
failed for " + dn;
+                                LOG_ER("%s", error.c_str());
+                                
SmfCampaignThread::instance()->campaign()->setError(error);
+                                delete p_uc; // To terminate and remove any 
previously started procedure threads
+                                /* Don't change campaign state to allow 
reexecution */
+                                return SA_AIS_OK;
+                        }
+
+                        iter++;
+                }
+        }
+        TRACE_LEAVE();
+        return SA_AIS_OK; //Will never return here, just for compiler
+}
+
 /** 
  * procResult
  * Takes care of procedure result
diff --git a/osaf/services/saf/smfsv/smfd/SmfCampaign.hh 
b/osaf/services/saf/smfsv/smfd/SmfCampaign.hh
--- a/osaf/services/saf/smfsv/smfd/SmfCampaign.hh
+++ b/osaf/services/saf/smfsv/smfd/SmfCampaign.hh
@@ -48,8 +48,13 @@
 #define SMF_CLUSTER_CONTROLLERS_ATTR "smfClusterControllers"
 #define SMF_SS_AFFECTED_NODES_ENABLE_ATTR "smfSSAffectedNodesEnable"
 #define SMF_KEEP_DU_STATE_ATTR    "smfKeepDuState"
+#define OPENSAF_SMF_EXEC_CONTROL  "openSafSmfExecControl"
 #define SMF_UPDATE_ELAPSED_TIME_INTERVAL 10000
 
+/* We need some DN space for the step (~15),activation/deactivation (~30)
+   and image node (~15) objects */
+#define OSAF_STEP_ACT_LENGTH 60
+
 class SmfUpgradeCampaign;
 class SmfUpgradeProcedure;
 
@@ -80,6 +85,7 @@ class SmfCampaign {
        SaAisErrorT adminOpVerify(void);
 
        SaAisErrorT initExecution(void);
+       SaAisErrorT startProcedureThreads(void);
 
         //    void procResult(SmfUpgradeProcedure* procedure, PROCEDURE_RESULT 
rc);
        /* TODO Remove procResult ?? */
diff --git a/osaf/services/saf/smfsv/smfd/SmfCampaignXmlParser.cc 
b/osaf/services/saf/smfsv/smfd/SmfCampaignXmlParser.cc
--- a/osaf/services/saf/smfsv/smfd/SmfCampaignXmlParser.cc
+++ b/osaf/services/saf/smfsv/smfd/SmfCampaignXmlParser.cc
@@ -1359,7 +1359,7 @@ SmfCampaignXmlParser::parseActivationUni
                        TRACE("xmlTag swRemove found");
                        SmfBundleRef br;
                        parseBundleRef(&br, n);
-                       scope->m_swRemowe.push_back(br);
+                       scope->m_swRemove.push_back(br);
 
                } else if ((!strcmp((char *)n->name, "swAdd")) && (n->ns == 
ns)) {
                        TRACE("xmlTag swAdd found");
diff --git a/osaf/services/saf/smfsv/smfd/SmfProcState.cc 
b/osaf/services/saf/smfsv/smfd/SmfProcState.cc
--- a/osaf/services/saf/smfsv/smfd/SmfProcState.cc
+++ b/osaf/services/saf/smfsv/smfd/SmfProcState.cc
@@ -25,6 +25,7 @@
 
 #include "logtrace.h"
 #include "osaf_extended_name.h"
+#include "SmfUpgradeCampaign.hh"
 #include "SmfUpgradeProcedure.hh"
 #include "SmfUpgradeStep.hh"
 #include "SmfProcState.hh"
@@ -240,13 +241,23 @@ SmfProcStateInitial::executeInit(SmfUpgr
 {
        TRACE_ENTER();
        LOG_NO("PROC: Start procedure init actions");
-
-       TRACE("SmfProcStateInitial::executeInit, Calculate steps");
-        if( !i_proc->calculateSteps() ) {
-                changeState(i_proc, SmfProcStateExecFailed::instance());
-                LOG_NO("SmfProcStateExecuting::executeInit:Step calculation 
failes");
-                TRACE_LEAVE();
-                return SMF_PROC_FAILED;
+        if 
(SmfCampaignThread::instance()->campaign()->getUpgradeCampaign()->getProcExecutionMode()
 
+           == SMF_MERGE_TO_SINGLE_STEP) {
+                LOG_NO("SmfProcStateInitial::executeInit, Merge procedures 
into single step");
+                if( !i_proc->mergeStepIntoSingleStep(i_proc)) {
+                        changeState(i_proc, 
SmfProcStateExecFailed::instance());
+                        LOG_NO("SmfProcStateExecuting::executeInit:Rolling to 
single merging failes");
+                        TRACE_LEAVE();
+                        return SMF_PROC_FAILED;
+                }
+        } else {
+                TRACE("SmfProcStateInitial::executeInit, Calculate steps");
+                if( !i_proc->calculateSteps() ) {
+                        changeState(i_proc, 
SmfProcStateExecFailed::instance());
+                        LOG_NO("SmfProcStateExecuting::executeInit:Step 
calculation failes");
+                        TRACE_LEAVE();
+                        return SMF_PROC_FAILED;
+                }
         }
 
        TRACE("SmfProcStateInitial::executeInit, Create step objects in IMM");
diff --git a/osaf/services/saf/smfsv/smfd/SmfStepState.cc 
b/osaf/services/saf/smfsv/smfd/SmfStepState.cc
--- a/osaf/services/saf/smfsv/smfd/SmfStepState.cc
+++ b/osaf/services/saf/smfsv/smfd/SmfStepState.cc
@@ -22,10 +22,12 @@
 #include "logtrace.h"
 #include "SmfUpgradeMethod.hh"
 #include "SmfUpgradeProcedure.hh"
+#include "SmfUpgradeCampaign.hh"
 #include "saSmf.h"
 #include "SmfUpgradeStep.hh"
 #include "SmfStepState.hh"
 #include "SmfStepTypes.hh"
+#include "smfd.h"
 
 /* ========================================================================
  *   DEFINITIONS
@@ -204,10 +206,21 @@ SmfStepStateExecuting::execute(SmfUpgrad
         SmfStepType* stepType = i_step->getStepType();
         if (stepType == NULL) {
                 /* We could have been restarted in this state e.g. at cluster 
reboot */
-                if (i_step->calculateStepType() != SA_AIS_OK) {
-                        LOG_ER("Failed to recalculate step type when trying to 
continue step %s", i_step->getDn().c_str());
-                        changeState(i_step, SmfStepStateFailed::instance());
-                        return SMF_STEP_FAILED;
+                if 
(SmfCampaignThread::instance()->campaign()->getUpgradeCampaign()->getProcExecutionMode()
+                   == SMF_MERGE_TO_SINGLE_STEP) {
+                        // If SMF_MERGE_TO_SINGLE_STEP is configured we can 
only come here after a cluster reboot
+                        if (i_step->calculateStepTypeForMergedSingle() != 
SA_AIS_OK) {
+                                LOG_ER("Failed to recalculate step type for 
merged single step when \
+                                        trying to continue step %s", 
i_step->getDn().c_str());
+                                changeState(i_step, 
SmfStepStateFailed::instance());
+                                return SMF_STEP_FAILED;
+                        }
+                } else {
+                        if (i_step->calculateStepType() != SA_AIS_OK) {
+                                LOG_ER("Failed to recalculate step type when 
trying to continue step %s", i_step->getDn().c_str());
+                                changeState(i_step, 
SmfStepStateFailed::instance());
+                                return SMF_STEP_FAILED;
+                        }
                 }
                 stepType = i_step->getStepType();
         }
diff --git a/osaf/services/saf/smfsv/smfd/SmfTargetTemplate.hh 
b/osaf/services/saf/smfsv/smfd/SmfTargetTemplate.hh
--- a/osaf/services/saf/smfsv/smfd/SmfTargetTemplate.hh
+++ b/osaf/services/saf/smfsv/smfd/SmfTargetTemplate.hh
@@ -113,6 +113,9 @@ public:
        inline std::string const& getClmNode() const {
                return m_clmNode;
        };
+       inline void setAmfNode(std::string& i_amfNode) {
+               m_amfNode = i_amfNode;
+       };
        inline std::string const& getAmfNode() const {
                return m_amfNode;
        };
@@ -187,7 +190,24 @@ class SmfBundleRef {
        inline const std::list<SmfPlmExecEnv>& getPlmExecEnvList() const {
                return m_plmExecEnvList;
        };
+  
+///
+/// Purpose: Add a PlmExecEnv objects.
+/// @param   i_plmExecEnv A PlmExecEnv object
+/// @return  None
+///
+       void addPlmExecEnv(const SmfPlmExecEnv& i_plmExecEnv)
+                { m_plmExecEnvList.push_back(i_plmExecEnv); }
 
+///
+/// Purpose: Append the list of PlmExecEnv objects.
+/// @param   i_plmExecEnvList A list of PlmExecEnv objects
+/// @return  None
+///
+       void addPlmExecEnvList(const std::list<SmfPlmExecEnv>& i_plmExecEnvList)
+                { m_plmExecEnvList.insert(m_plmExecEnvList.end(),
+                                          i_plmExecEnvList.begin(),
+                                          i_plmExecEnvList.end()); }
 
  private:
        friend class SmfCampaignXmlParser;
diff --git a/osaf/services/saf/smfsv/smfd/SmfUpgradeAction.cc 
b/osaf/services/saf/smfsv/smfd/SmfUpgradeAction.cc
--- a/osaf/services/saf/smfsv/smfd/SmfUpgradeAction.cc
+++ b/osaf/services/saf/smfsv/smfd/SmfUpgradeAction.cc
@@ -409,6 +409,14 @@ SmfAdminOperationAction::execute(SaImmOi
                                                const_cast<const 
SaImmAdminOperationParamsT_2 **>(params), 
                                                smfd_cb->adminOpTimeout);
 
+        //If an admin operation is already performed SA_AIS_ERR_NO_OP is 
returned
+        //Treat this as OK, just log it and return SA_AIS_OK from this method
+        if (rc == SA_AIS_ERR_NO_OP) {
+                LOG_NO("Admin op [%d] on [%s], return SA_AIS_ERR_NO_OP, 
treated as OK",
+                       m_doOpId, m_doDn.c_str());
+               rc = SA_AIS_OK;
+        }
+
        //Delete the mem hold by SaImmAdminOperationParamsT_2
        for (int i = 0; params[i] != 0; i++) {
                delete params[i];
diff --git a/osaf/services/saf/smfsv/smfd/SmfUpgradeAction.hh 
b/osaf/services/saf/smfsv/smfd/SmfUpgradeAction.hh
--- a/osaf/services/saf/smfsv/smfd/SmfUpgradeAction.hh
+++ b/osaf/services/saf/smfsv/smfd/SmfUpgradeAction.hh
@@ -413,6 +413,9 @@ class SmfCallbackAction:public SmfUpgrad
 
        SmfCallback & getCallback(void) { return m_callback; }
 
+       void setCallbackProcedure(SmfUpgradeProcedure *i_proc)
+               { m_callback.setProcedure(i_proc); }
+
  private:
 ///
 /// Purpose: Disables copy constructor.
diff --git a/osaf/services/saf/smfsv/smfd/SmfUpgradeCampaign.cc 
b/osaf/services/saf/smfsv/smfd/SmfUpgradeCampaign.cc
--- a/osaf/services/saf/smfsv/smfd/SmfUpgradeCampaign.cc
+++ b/osaf/services/saf/smfsv/smfd/SmfUpgradeCampaign.cc
@@ -73,7 +73,8 @@ class SmfUpgradeProcedure;
     m_waitToCommit(0),
     m_waitToAllowNewCampaign(0),
     m_noOfExecutingProc(0),
-    m_noOfProcResponses(0)
+    m_noOfProcResponses(0),
+    m_procExecutionMode(0)
 {
 
 }
@@ -84,7 +85,14 @@ class SmfUpgradeProcedure;
 SmfUpgradeCampaign::~SmfUpgradeCampaign()
 {
        TRACE_ENTER();
-       //Delete procedures
+        //Delete merged procedure first since it contain references to other 
proc
+       //Check campaign state, if verify fails the campaign is still in state 
initial
+       //and the merged procedure is not yet created.
+       if ((getProcExecutionMode() == SMF_MERGE_TO_SINGLE_STEP) &&
+           (m_state->getState() != SA_SMF_CMPG_INITIAL)) {
+                delete(m_mergedProcedure);
+        }
+
        std::vector < SmfUpgradeProcedure * >::iterator iter;
 
        for (iter = m_procedure.begin(); iter != m_procedure.end(); ++iter) {
@@ -1008,6 +1016,16 @@ SmfUpgradeCampaign::continueExec()
             currentState = m_state->getState();
         }
 
+        //Start procedure threads
+        if (SmfCampaignThread::instance()->campaign()->startProcedureThreads() 
!= SA_AIS_OK) {
+                LOG_NO("continueExec() fail to restart procedure threads");
+               std::string error = "Fail to restart procedure threads";
+               SmfCampaignThread::instance()->campaign()->setError(error);
+               changeState(SmfCampStateExecFailed::instance());
+               TRACE_LEAVE();
+               return;
+        }
+
         switch (currentState) {
         case SA_SMF_CMPG_EXECUTING:
                 SmfCampaignThread::instance()->campaign()->startElapsedTime();
diff --git a/osaf/services/saf/smfsv/smfd/SmfUpgradeCampaign.hh 
b/osaf/services/saf/smfsv/smfd/SmfUpgradeCampaign.hh
--- a/osaf/services/saf/smfsv/smfd/SmfUpgradeCampaign.hh
+++ b/osaf/services/saf/smfsv/smfd/SmfUpgradeCampaign.hh
@@ -406,6 +406,30 @@ void verify();
 ///
        const std::vector < SmfUpgradeProcedure * >& getProcedures() { return 
m_procedure; }
 
+/// Purpose: set the merged procedure
+/// @param   A SmfUpgradeProcedure *
+/// @return  the procedure.
+///
+       void setMergedProc(SmfUpgradeProcedure * proc) { m_mergedProcedure = 
proc; }
+
+/// Purpose: get the merged procedure
+/// @param   None.
+/// @return  the procedure.
+///
+       SmfUpgradeProcedure * getMergedProc() { return m_mergedProcedure; }
+
+/// Purpose: Set the procedure ecxecution mode
+/// @param   The execution mode.
+/// @return  none
+///
+       void setProcExecutionMode(int i_procExecutionMode) { 
m_procExecutionMode = i_procExecutionMode; }
+
+/// Purpose: Get the procedure ecxecution mode
+/// @param   none
+/// @return  The execution mode.
+///
+       int getProcExecutionMode() { return m_procExecutionMode; }
+
        SmfCampaignInit & getCampaignInit() { return  m_campInit; }
        SmfCampaignWrapup & getCampaignWrapup() { return  m_campWrapup; }
 
@@ -459,9 +483,11 @@ private:
        SmfCampaignInit m_campInit;
        SmfCampaignWrapup m_campWrapup;
         std::vector < SmfUpgradeProcedure * >m_procedure;
+        SmfUpgradeProcedure * m_mergedProcedure;
         SaTimeT m_waitToCommit;
         SaTimeT m_waitToAllowNewCampaign;
        int m_noOfExecutingProc;
         int m_noOfProcResponses;
+       int m_procExecutionMode;
 };
 #endif                         // __SMFUPGRADECAMPAIGN_H
diff --git a/osaf/services/saf/smfsv/smfd/SmfUpgradeMethod.hh 
b/osaf/services/saf/smfsv/smfd/SmfUpgradeMethod.hh
--- a/osaf/services/saf/smfsv/smfd/SmfUpgradeMethod.hh
+++ b/osaf/services/saf/smfsv/smfd/SmfUpgradeMethod.hh
@@ -344,7 +344,7 @@ public:
                return m_added;
        };
        inline std::list<SmfBundleRef> const& getSwRemove() const {
-               return m_swRemowe;
+               return m_swRemove;
        };
        inline std::list<SmfBundleRef> const& getSwAdd() const {
                return m_swAdd;
@@ -355,7 +355,7 @@ private:
        std::list<SmfEntity> m_actedOn;
        std::list<SmfEntity> m_removed;
        std::list<SmfImmCreateOperation> m_added;
-       std::list<SmfBundleRef> m_swRemowe;
+       std::list<SmfBundleRef> m_swRemove;
        std::list<SmfBundleRef> m_swAdd;
 };
 
diff --git a/osaf/services/saf/smfsv/smfd/SmfUpgradeProcedure.cc 
b/osaf/services/saf/smfsv/smfd/SmfUpgradeProcedure.cc
--- a/osaf/services/saf/smfsv/smfd/SmfUpgradeProcedure.cc
+++ b/osaf/services/saf/smfsv/smfd/SmfUpgradeProcedure.cc
@@ -98,7 +98,8 @@ unsigned long SmfUpgradeProcedure::s_pro
     m_beforeTerm(0),
     m_afterImmModify(0),
     m_afterInstantiate(0),
-    m_afterUnlock(0)
+    m_afterUnlock(0),
+    m_isMergedProcedure(false)
 {
     // create and set the OI name of the procedure
     std::stringstream ss;
@@ -118,30 +119,33 @@ SmfUpgradeProcedure::~SmfUpgradeProcedur
 {
        TRACE_ENTER();
        if (m_procedureThread != NULL) {
-               m_procedureThread->stop();
+                m_procedureThread->stop();
                /* The thread deletes it's own object when terminating */
                m_procedureThread = NULL;
        }
+
        delete m_upgradeMethod;
 
-       std::vector < SmfUpgradeAction * >::iterator it;
-
-       /* Delete procedure initialization */
-       for (it = m_procInitAction.begin(); it != m_procInitAction.end(); ++it) 
{
-               delete(*it);
-       }
-
-       /* Delete procedure wrapup */
-       for (it = m_procWrapupAction.begin(); it != m_procWrapupAction.end(); 
++it) {
-               delete(*it);
-       }
-
-       std::vector < SmfUpgradeStep * >::iterator stepit;
-
-       /* Delete upgrade steps */
-       for (stepit = m_procSteps.begin(); stepit != m_procSteps.end(); 
++stepit) {
-               delete(*stepit);
-       }
+        //No delete if merged procedure, deletions are made by original 
procedures
+        if (m_isMergedProcedure == false) {
+                std::vector < SmfUpgradeAction * >::iterator it;
+
+                /* Delete procedure initialization */
+                for (it = m_procInitAction.begin(); it != 
m_procInitAction.end(); ++it) {
+                        delete(*it);
+                }
+
+               /* Delete procedure wrapup */
+                for (it = m_procWrapupAction.begin(); it != 
m_procWrapupAction.end(); ++it) {
+                        delete(*it);
+                }
+
+                /* Delete upgrade steps */
+                std::vector < SmfUpgradeStep * >::iterator stepit;
+                for (stepit = m_procSteps.begin(); stepit != 
m_procSteps.end(); ++stepit) {
+                        delete(*stepit);
+                }
+        }
 
        TRACE_LEAVE();
 }
@@ -466,7 +470,6 @@ SmfUpgradeProcedure::switchOver()
 
        TRACE_LEAVE();
 }
-
 
//------------------------------------------------------------------------------
 // calculateSteps()
 
//------------------------------------------------------------------------------
@@ -475,12 +478,11 @@ SmfUpgradeProcedure::calculateSteps()
 {
        TRACE_ENTER();
        SmfUpgradeMethod *upgradeMethod = NULL;
-       std::multimap<std::string, objectInst> objInstances;
-
-       if (!getImmComponentInfo(objInstances)) {
-               LOG_NO("SmfUpgradeProcedure::calculateSteps: Config info from 
IMM could not be read");
-               return false;
-       }
+        std::multimap<std::string, objectInst> objects;
+        if (!getImmComponentInfo(objects)) {
+                LOG_NO("SmfUpgradeProcedure::calculateSteps: Config info from 
IMM could not be read");
+                return false;
+        }
 
        upgradeMethod = getUpgradeMethod();
 
@@ -492,7 +494,7 @@ SmfUpgradeProcedure::calculateSteps()
        switch (upgradeMethod->getUpgradeMethod()) {
        case SA_SMF_ROLLING:
                {
-                       if ( !calculateRollingSteps((SmfRollingUpgrade 
*)upgradeMethod, objInstances)) {
+                       if ( !calculateRollingSteps((SmfRollingUpgrade 
*)upgradeMethod, objects)) {
                                 
LOG_NO("SmfUpgradeProcedure::calculateSteps:calculateRollingSteps failed");
                                 return false;
                         }
@@ -501,7 +503,51 @@ SmfUpgradeProcedure::calculateSteps()
 
        case SA_SMF_SINGLE_STEP:
                {
-                       if ( 
!calculateSingleStep((SmfSinglestepUpgrade*)upgradeMethod, objInstances)) {
+                       if ( 
!calculateSingleStep((SmfSinglestepUpgrade*)upgradeMethod, objects)) {
+                                
LOG_NO("SmfUpgradeProcedure::calculateSteps:calculateSingleStep failed");
+                                return false;
+                        }
+                       break;
+               }
+
+       default:
+               {
+                       LOG_NO("SmfUpgradeProcedure::calculateSteps unknown 
upgrade method found %d", upgradeMethod->getUpgradeMethod());
+                       return false;
+               }
+       }
+
+       TRACE_LEAVE();
+        return true;
+}
+
+//------------------------------------------------------------------------------
+// calculateSteps()
+//------------------------------------------------------------------------------
+bool 
+SmfUpgradeProcedure::calculateSteps(std::multimap<std::string, objectInst>& 
i_objects)
+{
+       TRACE_ENTER();
+       SmfUpgradeMethod *upgradeMethod = getUpgradeMethod();
+
+       if (upgradeMethod == NULL) {
+               LOG_NO("SmfUpgradeProcedure::calculateSteps: calculateSteps no 
upgrade method found");
+               return false;
+       }
+
+       switch (upgradeMethod->getUpgradeMethod()) {
+       case SA_SMF_ROLLING:
+               {
+                       if ( !calculateRollingSteps((SmfRollingUpgrade 
*)upgradeMethod, i_objects)) {
+                                
LOG_NO("SmfUpgradeProcedure::calculateSteps:calculateRollingSteps failed");
+                                return false;
+                        }
+                       break;
+               }
+
+       case SA_SMF_SINGLE_STEP:
+               {
+                       if ( 
!calculateSingleStep((SmfSinglestepUpgrade*)upgradeMethod, i_objects)) {
                                 
LOG_NO("SmfUpgradeProcedure::calculateSteps:calculateSingleStep failed");
                                 return false;
                         }
@@ -570,7 +616,8 @@ SmfUpgradeProcedure::calculateRollingSte
                        stepCntr++;
                         snprintf(rdnStr, rdnStrSize, "safSmfStep=%04u", 
stepCntr);
 
-                       SmfUpgradeStep *newStep = new SmfUpgradeStep();
+                       SmfUpgradeStep *newStep = new(std::nothrow) 
SmfUpgradeStep;
+                        osafassert(newStep != NULL);
                        newStep->setRdn(rdnStr);
                        newStep->setDn(newStep->getRdn() + "," + getDn());
                        unitNameAndState tmp;
@@ -627,7 +674,7 @@ SmfUpgradeProcedure::calculateRollingSte
                        stepCntr++;
                         snprintf(rdnStr, rdnStrSize, "safSmfStep=%04u", 
stepCntr);
 
-                        SmfUpgradeStep *newStep = new(std::nothrow) 
SmfUpgradeStep();
+                        SmfUpgradeStep *newStep = new(std::nothrow) 
SmfUpgradeStep;
                         osafassert(newStep != NULL);
                         newStep->setRdn(rdnStr);
                         newStep->setDn(newStep->getRdn() + "," + getDn());
@@ -681,7 +728,8 @@ SmfUpgradeProcedure::calculateRollingSte
                        stepCntr++;
                         snprintf(rdnStr, rdnStrSize, "safSmfStep=%04u", 
stepCntr);
 
-                       SmfUpgradeStep *newStep = new SmfUpgradeStep();
+                       SmfUpgradeStep *newStep = new(std::nothrow) 
SmfUpgradeStep;
+                        osafassert(newStep != NULL);
                        newStep->setRdn(rdnStr);
                        newStep->setDn(newStep->getRdn() + "," + getDn());
                        
newStep->setMaxRetry(i_rollingUpgrade->getStepMaxRetryCount());
@@ -794,12 +842,13 @@ bool SmfUpgradeProcedure::calculateSingl
                                              std::multimap<std::string, 
objectInst> &i_objects)
 {
         TRACE_ENTER();
-       SmfUpgradeStep *newStep = new SmfUpgradeStep();
+       SmfUpgradeStep *newStep = new(std::nothrow) SmfUpgradeStep;
+        osafassert(newStep != NULL);
        const SmfUpgradeScope* scope = i_upgrade->getUpgradeScope();
        const SmfForAddRemove* forAddRemove = 
                dynamic_cast<const SmfForAddRemove*>(scope);
 
-       newStep->setRdn("safSmfStep=1");
+       newStep->setRdn("safSmfStep=0001");
        newStep->setDn(newStep->getRdn() + "," + getDn());
        newStep->setMaxRetry(i_upgrade->getStepMaxRetryCount());
        newStep->setRestartOption(i_upgrade->getStepRestartOption());
@@ -1089,6 +1138,452 @@ bool SmfUpgradeProcedure::calculateSingl
 }
 
 
//------------------------------------------------------------------------------
+// mergeStepIntoSingleStep()
+//------------------------------------------------------------------------------
+bool 
+SmfUpgradeProcedure::mergeStepIntoSingleStep(SmfUpgradeProcedure * i_proc, 
SmfUpgradeStep *i_newStep)
+{
+        TRACE_ENTER();
+       std::multimap<std::string, objectInst> objInstances;
+        SmfUpgradeStep *newStep;
+
+       if (!getImmComponentInfo(objInstances)) {
+               LOG_NO("SmfUpgradeProcedure::calculateSteps: Config info from 
IMM could not be read");
+               return false;
+       }
+
+        if (i_newStep == 0) {
+                newStep = new(std::nothrow) SmfUpgradeStep;
+                osafassert(newStep != NULL);
+        } else {
+                newStep = i_newStep;
+        }
+
+       newStep->setRdn("safSmfStep=0001");
+       newStep->setDn(newStep->getRdn() + "," + getDn());
+       newStep->setMaxRetry(0);
+       newStep->setRestartOption(0);
+
+        std::list < unitNameAndState > forAddRemoveAU;
+        std::list < unitNameAndState > forAddRemoveDU;
+       std::list < unitNameAndState > tmpDU;
+        SmfUpgradeCampaign * camp = 
SmfCampaignThread::instance()->campaign()->getUpgradeCampaign();
+        const std::vector < SmfUpgradeProcedure * >& procedures = 
camp->getProcedures();
+        std::vector < SmfUpgradeProcedure * >::const_iterator proc_iter;
+        for (proc_iter = procedures.begin(); proc_iter != procedures.end(); 
proc_iter++) {
+                LOG_NO("Merging [%s] into a single step procedure", 
(*proc_iter)->getName().c_str());
+                //Calculate the steps of the campaign.xml procedures
+                LOG_NO("Calculate the procedure steps");
+                if( !(*proc_iter)->calculateSteps(objInstances) ) {
+                        LOG_NO("SmfProcStateExecuting::executeInit:Step 
calculation failes");
+                        TRACE_LEAVE();
+                        return false;
+                }
+
+                //Append the information in the new single step with info from 
the calculated steps above.
+                //For all steps in the procedure
+                std::vector < SmfUpgradeStep * >::const_iterator step_iter;
+                const std::vector < SmfUpgradeStep * >& steps = 
(*proc_iter)->getProcSteps();
+                for (step_iter = steps.begin(); step_iter != steps.end(); 
step_iter++) {
+                        LOG_NO("Step = %s", (*step_iter)->getDn().c_str());
+                        LOG_NO("Copy activation/deactivation units");
+
+                        if 
((*proc_iter)->getUpgradeMethod()->getUpgradeMethod() == SA_SMF_ROLLING) { 
//SA_SMF_ROLLING
+                                //Add the DU list, AU list will be created 
later as a copy of DU list.
+                               tmpDU.insert(tmpDU.end(),
+                                            
(*step_iter)->getDeactivationUnitList().begin(),
+                                            
(*step_iter)->getDeactivationUnitList().end());
+                                //Merge (rolling) step bundle ref into the new 
single step
+                                mergeBundleRefRollingToSingleStep(newStep, 
(*step_iter));
+                        } else { //SA_SMF_SINGLE_STEP
+                                if (dynamic_cast<const 
SmfForAddRemove*>((*proc_iter)->getUpgradeMethod()->getUpgradeScope()) != NULL) 
{
+                                        //The scope of the single step is 
forAddRemove
+                                        //Add the AU/DU lists The lists must 
be added "as is" e.g. a SU unlock must be run
+                                        //even if the hosting node is unlocked.
+
+                                        //Copy AU/DU to local temp list
+                                        
forAddRemoveAU.insert(forAddRemoveAU.end(),
+                                                              
(*step_iter)->getActivationUnitList().begin(),
+                                                              
(*step_iter)->getActivationUnitList().end());
+                                        
forAddRemoveDU.insert(forAddRemoveDU.end(),
+                                                              
(*step_iter)->getDeactivationUnitList().begin(),
+                                                              
(*step_iter)->getDeactivationUnitList().end());
+
+                                        //Merge (single for add remove) step 
bundle ref into the new single step
+                                        
mergeBundleRefSingleStepToSingleStep(newStep, (*step_iter));
+                                } else if (dynamic_cast<const 
SmfForModify*>((*proc_iter)->getUpgradeMethod()->getUpgradeScope()) != NULL) {
+                                        //The scope of the single step is 
forModify
+                                        //Add the DU list, AU list will be 
created later as a copy of DU list.
+                                        
//newStep->addDeactivationUnits((*step_iter)->getDeactivationUnitList());
+                                       tmpDU.insert(tmpDU.end(),
+                                                    
(*step_iter)->getDeactivationUnitList().begin(),
+                                                    
(*step_iter)->getDeactivationUnitList().end());
+                                        //Merge (single for modify) step 
bundle ref into the new single step
+                                        
mergeBundleRefSingleStepToSingleStep(newStep, (*step_iter));
+                                } else {
+                                        
LOG_NO("SmfUpgradeProcedure::mergeStepIntoSingleStep: Procedure scope not found 
(forAddRemove/forModify)");
+                                        delete newStep;
+                                        TRACE_LEAVE();
+                                        return false;
+                                }
+                        }
+
+                        LOG_NO("Add modifications");
+                        std::list < SmfImmOperation * >& qq = 
(*step_iter)->getModifications();
+                        LOG_NO("old step modifications size() = %lu", 
qq.size());
+
+                        
newStep->addModifications((*step_iter)->getModifications());
+                        std::list < SmfImmOperation * >& rr = 
newStep->getModifications();
+                        LOG_NO("newStep merged modifications size() = %lu", 
rr.size());
+                }
+
+               //The init actions
+               LOG_NO("Copy the procedure init actions");
+               i_proc->addInitActions((*proc_iter)->getInitActions());
+               std::vector <SmfUpgradeAction*>::const_iterator actioniter;
+               actioniter = i_proc->getInitActions().begin();
+               while (actioniter != i_proc->getInitActions().end()) {
+                       const SmfCallbackAction* cbkAction =
+                               dynamic_cast<const 
SmfCallbackAction*>(*actioniter);
+                       if (cbkAction != NULL) {
+                               
const_cast<SmfCallbackAction*>(cbkAction)->setCallbackProcedure(this);
+                       }
+                       actioniter++;
+               }
+
+               //The wrapup actions
+               LOG_NO("Copy the procedure wrapup actions");
+               i_proc->addWrapupActions((*proc_iter)->getWrapupActions());
+               actioniter = i_proc->getWrapupActions().begin();
+               while (actioniter != i_proc->getWrapupActions().end()) {
+                       const SmfCallbackAction* cbkAction =
+                               dynamic_cast<const 
SmfCallbackAction*>(*actioniter);
+                       if (cbkAction != NULL) {
+                               
const_cast<SmfCallbackAction*>(cbkAction)->setCallbackProcedure(this);
+                       }
+                       actioniter++;
+               }
+
+               //The step callbacks
+               getCallbackList((*proc_iter)->getUpgradeMethod());
+        }
+
+        //Remove DU duplicates
+        LOG_NO("Remove duplicates from the merged DU list");
+        tmpDU.sort(compare_du_part);
+        tmpDU.unique(unique_du_part);
+
+        //Reduce the DU list, check if smaller scope is within bigger scope. 
+        LOG_NO("Optimize AU/DU");
+       std::pair<std::multimap<std::string, objectInst>::iterator, 
+                 std::multimap<std::string, objectInst>::iterator> nodeName_mm;
+       std::multimap<std::string, objectInst>::iterator iter;
+
+       std::list < unitNameAndState > nodeLevelDU;
+        std::list < unitNameAndState >::iterator unit_iter;
+       //Find DU on node level and save them in a separate list
+        for (unit_iter = tmpDU.begin(); unit_iter != tmpDU.end();) {
+                if ((*unit_iter).name.find("safAmfNode=") == 0) {        //DU 
is a node node
+                       nodeLevelDU.push_back(*unit_iter);               //A 
node will never be optimized away, save it
+                       unit_iter = tmpDU.erase(unit_iter);              
//Remove the node and update iterator
+               } else {
+                       unit_iter++;
+               }
+       }
+
+       //For all found nodes, look if some other DU (comp/SU) is within scope
+       //tmpDU contain all DU except the node level ones which was removed 
above and saved in nodeLevelDU list
+       std::list < unitNameAndState >::iterator node_iter;
+        for (node_iter = nodeLevelDU.begin(); node_iter != nodeLevelDU.end(); 
node_iter++) {
+               //For all comp/SU found in the scope of the node.
+               //Find out if any remaining DU is within it
+               nodeName_mm = objInstances.equal_range((*node_iter).name); 
//Get all components/SU within the node
+               for (iter = nodeName_mm.first;  iter != nodeName_mm.second;  
++iter) {
+                       //For all comp/SU sound in the scope of the node.
+                       //Find out if any remaininf DU is within it
+                       for (unit_iter = tmpDU.begin(); unit_iter != 
tmpDU.end();) {
+                               if ((*unit_iter).name.find("safSu=") == 0) 
{//SU as AU/DU
+                                       if ((*unit_iter).name == 
(*iter).second.suDN) {  //Check SU
+                                               LOG_NO("[%s] is in scope of 
[%s], remove it from DU list",
+                                                      
(*unit_iter).name.c_str(), (*node_iter).name.c_str());
+                                               unit_iter = 
tmpDU.erase(unit_iter); //Remove the node and update iterator
+                                       } else if ((*unit_iter).name == 
(*iter).second.compDN) { //Check comp
+                                               LOG_NO("[%s] is in scope of 
[%s], remove it from DU list",
+                                                      
(*unit_iter).name.c_str(), (*node_iter).name.c_str());
+                                               unit_iter = 
tmpDU.erase(unit_iter); //Remove the node and update iterator
+                                       } else {
+                                               unit_iter++;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       //tmpDU contain all DU which was not in the scope of an included node
+       //Find DU on SU level and save them in a separate list. Remove SU from 
tmpDU list
+       std::list < unitNameAndState > suLevelDU;
+        for (unit_iter = tmpDU.begin(); unit_iter != tmpDU.end();) {
+                if ((*unit_iter).name.find("safSu=") == 0) {             //DU 
is a SU
+                       suLevelDU.push_back(*unit_iter);                 //A 
node will never be optimized away, save it
+                       unit_iter = tmpDU.erase(unit_iter);              
//Remove the SU and update iterator
+               } else {
+                       unit_iter++;
+               }
+       }
+
+       //For all SU in the suLevelDU list, look if remaining DU in tmpDU is 
within scope of the SU
+       std::list < unitNameAndState >::iterator su_iter;
+       for (su_iter = suLevelDU.begin(); su_iter != suLevelDU.end(); 
su_iter++) {
+               for (unit_iter = tmpDU.begin(); unit_iter != tmpDU.end();) {
+                       if ((*unit_iter).name.find((*su_iter).name) != 
std::string::npos) {
+                               //The component was in the scope of the SU
+                               LOG_NO("[%s] is in scope of [%s], remove it 
from DU list",
+                                                      
(*unit_iter).name.c_str(), (*su_iter).name.c_str());
+                               unit_iter = tmpDU.erase(unit_iter); //Remove 
the Component and update iterator
+                       } else {
+                               unit_iter++;
+                       }
+               }
+       }
+
+        newStep->addDeactivationUnits(nodeLevelDU);  //Add the node level DU
+       newStep->addDeactivationUnits(suLevelDU);    //Add the SU level DU
+       newStep->addDeactivationUnits(tmpDU);        //Add the comp level DU
+       newStep->addActivationUnits(nodeLevelDU);    //Rolling and forModify 
are symetric, add the node level DU
+        newStep->addActivationUnits(suLevelDU);      //Rolling and forModify 
are symetric, Add the SU level DU
+        newStep->addActivationUnits(tmpDU);          //Rolling and forModify 
are symetric, Add the comp level DU
+
+        //Copy the forAddRemove AU/DU into the lists as is. They must be run 
as specified in the campaign.
+        newStep->addDeactivationUnits(forAddRemoveDU);
+        newStep->addActivationUnits(forAddRemoveAU);
+
+        //Add the merged single step to the procedure if allocated in this 
method
+        if (i_newStep == 0) {
+                i_proc->addProcStep(newStep);
+        }
+
+        TRACE_LEAVE();
+        return true;
+}
+
+//------------------------------------------------------------------------------
+// mergeBundleRefSingleStepToSingleStep()
+//------------------------------------------------------------------------------
+bool
+SmfUpgradeProcedure::mergeBundleRefSingleStepToSingleStep(SmfUpgradeStep * 
io_newStep,
+                                                          SmfUpgradeStep * 
i_oldStep)
+{
+        //Set the node from the step into bundle plmExecEnvList
+        std::list < SmfBundleRef >::iterator oldStepBundleIter;
+        std::list < SmfBundleRef >::iterator newStepBundleIter;
+        //Add the old steps AMF node to the plmExecEnv of the bundle ref to 
make it
+        //to install on the correct node/nodes.
+
+        LOG_NO("Merge SwAddLists from the single step into a single step 
bundle list");
+        //Read the bundles to add from the old step
+        std::list < SmfBundleRef > & bundlesOldStep = 
i_oldStep->getSwAddList();
+        LOG_NO("SwAddLists from old step contain [%lu] elements", 
bundlesOldStep.size());
+        for (oldStepBundleIter = bundlesOldStep.begin(); oldStepBundleIter != 
bundlesOldStep.end(); oldStepBundleIter++) {
+                std::list < SmfBundleRef >::iterator newStepBundleIter;
+
+                //Read the list of already saved bundles in the new step, if 
already exist only add the
+                //swNode's to the existing bundle
+                std::list < SmfBundleRef > & bundleNewStep = 
io_newStep->getSwAddList();
+                bool bundle_exists = false;
+
+                //Check if bundle from the old step already exist in the new 
step
+                for (newStepBundleIter = bundleNewStep.begin(); 
newStepBundleIter != bundleNewStep.end(); newStepBundleIter++) {
+                        LOG_NO("swAdd: (*newStepBundleIter).getBundleDn() = 
%s, (*oldStepBundleIter).getBundleDn() = %s",
+                               (*newStepBundleIter).getBundleDn().c_str(),
+                               (*oldStepBundleIter).getBundleDn().c_str());
+                        if ((*newStepBundleIter).getBundleDn() == 
(*oldStepBundleIter).getBundleDn()) {
+                                //Bundle already exist in the new single step
+                                //-If the bundle to add contain a plmExecEnv 
list, add that list of nodes to
+                                // the existing SmfBundleRef.
+                                //-If the bundle to add does not contain a 
plmExecEnv list, add the step nodes
+                                // to the existing SmfBundleRef.
+                                const std::list<SmfPlmExecEnv>& 
tmpPlmExecEnvList = (*oldStepBundleIter).getPlmExecEnvList();
+                                if (tmpPlmExecEnvList.size() != 0) {
+                                        
(*newStepBundleIter).addPlmExecEnvList(tmpPlmExecEnvList);
+                                } else {
+                                        const std::list<std::string> nodelist 
= i_oldStep->getSwNodeList();
+                                        std::list<std::string>::const_iterator 
str_iter;
+                                        for (str_iter = nodelist.begin(); 
str_iter != nodelist.end(); str_iter++) {
+                                                SmfPlmExecEnv plm;
+                                                
plm.setAmfNode(const_cast<std::string &>((*str_iter)));
+                                                //Copy the new SmfPlmExecEnv 
into the bundle plvExecEnv list
+                                               
(*newStepBundleIter).addPlmExecEnv(plm);
+                                        }
+                                }
+
+                                bundle_exists = true;
+                                LOG_NO("Existing Bundle = %s", 
(*oldStepBundleIter).getBundleDn().c_str());
+                        }
+                }
+
+                if (bundle_exists == false) {
+                        //New bundle, add the AMF nodes and save in the single 
step
+                        //If the new bundle does not contain a plmExecEnv 
list, add the step nodes to the plmExecEnv list
+                        if ((*oldStepBundleIter).getPlmExecEnvList().size() == 
0) {
+                                const std::list<std::string> nodelist = 
i_oldStep->getSwNodeList();
+                                std::list<std::string>::const_iterator 
str_iter;
+                                for (str_iter = nodelist.begin(); str_iter != 
nodelist.end(); str_iter++) {
+                                        SmfPlmExecEnv plm;
+                                        plm.setAmfNode(const_cast<std::string 
&>((*str_iter)));
+                                        //Copy the new SmfPlmExecEnv into the 
bundle plvExecEnv list
+                                        
(*oldStepBundleIter).addPlmExecEnv(plm);
+                                }
+                        }
+
+                        LOG_NO("New Bundle = %s added", 
(*oldStepBundleIter).getBundleDn().c_str());
+                        io_newStep->addSwAdd((*oldStepBundleIter));
+                }
+        }
+
+        LOG_NO("Merge SwRemoveLists from the single step into a single step 
bundle list");
+        //Read the bundles to remove from the old step swRemove list
+        bundlesOldStep = i_oldStep->getSwRemoveList();
+        for (oldStepBundleIter = bundlesOldStep.begin(); oldStepBundleIter != 
bundlesOldStep.end(); oldStepBundleIter++) {
+                std::list < SmfBundleRef >::iterator newStepBundleIter;
+
+                //Read the list of already saved bundles, if already exist add 
the new
+                //swNode's to the existing bundle
+                std::list < SmfBundleRef > & bundleNewStep = 
io_newStep->getSwRemoveList();
+                bool bundle_exists = false;
+
+                //Check if bundle from the old step already exist in the new 
step
+                for (newStepBundleIter = bundleNewStep.begin(); 
newStepBundleIter != bundleNewStep.end(); newStepBundleIter++) {
+                        LOG_NO("swAdd: (*newStepBundleIter).getBundleDn() = 
%s, (*oldStepBundleIter).getBundleDn() = %s",
+                               (*newStepBundleIter).getBundleDn().c_str(),
+                               (*oldStepBundleIter).getBundleDn().c_str());
+                        if ((*newStepBundleIter).getBundleDn() == 
(*oldStepBundleIter).getBundleDn()) {
+                                //Bundle already exist in the new single step
+                                //-If the bundle to add contain a plmExecEnv 
list, add that list of nodes to
+                                // the existing SmfBundleRef.
+                                //-If the bundle to add does not contain a 
plmExecEnv list, add the step nodes
+                                // to the existing SmfBundleRef.
+                                const std::list<SmfPlmExecEnv>& 
tmpPlmExecEnvList = (*oldStepBundleIter).getPlmExecEnvList();
+                                if (tmpPlmExecEnvList.size() != 0) {
+                                        
(*newStepBundleIter).addPlmExecEnvList(tmpPlmExecEnvList);
+                                } else {
+                                        const std::list<std::string> nodelist 
= i_oldStep->getSwNodeList();
+                                        std::list<std::string>::const_iterator 
str_iter;
+                                        for (str_iter = nodelist.begin(); 
str_iter != nodelist.end(); str_iter++) {
+                                                SmfPlmExecEnv plm;
+                                                
plm.setAmfNode(const_cast<std::string &>((*str_iter)));
+                                                //Copy the new SmfPlmExecEnv 
into the bundle plvExecEnv list
+                                                
(*newStepBundleIter).addPlmExecEnv(plm);
+                                        }
+                                }
+
+                                bundle_exists = true;
+                                LOG_NO("Existing Bundle = %s", 
(*oldStepBundleIter).getBundleDn().c_str());
+                        }
+                }
+
+                if (bundle_exists == false) {
+                        //New bundle, add the AMF nodes and save in the single 
step
+                        //If the new bundle does not contain a plmExecEnv 
list, add the step nodes to the plmExecEnv list
+                        if ((*oldStepBundleIter).getPlmExecEnvList().size() == 
0) {
+                                const std::list<std::string> nodelist = 
i_oldStep->getSwNodeList();
+                                std::list<std::string>::const_iterator 
str_iter;
+                                for (str_iter = nodelist.begin(); str_iter != 
nodelist.end(); str_iter++) {
+                                        SmfPlmExecEnv plm;
+                                        plm.setAmfNode(const_cast<std::string 
&>((*str_iter)));
+                                        //Copy the new SmfPlmExecEnv into the 
bundle plvExecEnv list
+                                        
(*oldStepBundleIter).addPlmExecEnv(plm);
+                                }
+                        }
+
+                        LOG_NO("New Bundle = %s added", 
(*oldStepBundleIter).getBundleDn().c_str());
+                        io_newStep->addSwRemove((*oldStepBundleIter));
+                }
+        }
+
+        return true;
+}
+
+//------------------------------------------------------------------------------
+// mergeBundleRefRollingToSingleStep()
+//------------------------------------------------------------------------------
+bool
+SmfUpgradeProcedure::mergeBundleRefRollingToSingleStep(SmfUpgradeStep * 
io_newStep,
+                                                       SmfUpgradeStep * 
i_oldStep)
+{
+       TRACE_ENTER();
+        //Set the node from the step into bundle plmExecEnvList
+        std::list < SmfBundleRef >::iterator oldStepBundleIter;
+        std::list < SmfBundleRef >::iterator newStepBundleIter;
+
+        //Add the old steps AMF node to the plmExecEnv of the bundle ref to 
make it
+        //install on the right node/nodes.
+
+        std::list < SmfBundleRef > & bundlesOldStep = 
i_oldStep->getSwAddList();
+        for (oldStepBundleIter = bundlesOldStep.begin(); oldStepBundleIter != 
bundlesOldStep.end(); oldStepBundleIter++) {
+                //Read the list of already saved bundles, if already exist 
only add the new
+                //swNode to the existing bundle
+                std::list < SmfBundleRef >::iterator newStepBundleIter;
+                std::list < SmfBundleRef > & bundlesNewStep = 
io_newStep->getSwAddList();
+                //Check if bundle already saved
+                bool bundle_exists = false;
+                for (newStepBundleIter = bundlesNewStep.begin(); 
newStepBundleIter != bundlesNewStep.end(); newStepBundleIter++) {
+                        LOG_NO("(*newStepBundleIter).getBundleDn() = %s, 
(*oldStepBundleIter).getBundleDn() = %s",
+                               (*newStepBundleIter).getBundleDn().c_str(),
+                               (*oldStepBundleIter).getBundleDn().c_str());
+                        if ((*newStepBundleIter).getBundleDn() == 
(*oldStepBundleIter).getBundleDn()) {
+                                //Bundle already saved in the single step, 
just add the AMF the node
+                                SmfPlmExecEnv plm;
+                                plm.setAmfNode(const_cast<std::string 
&>(i_oldStep->getSwNode()));
+                                (*newStepBundleIter).addPlmExecEnv(plm);
+                                bundle_exists = true;
+                                LOG_NO("Existing Bundle = %s, AmfNode = %s", 
(*oldStepBundleIter).getBundleDn().c_str()  ,plm.getAmfNode().c_str());
+                        }
+                }
+
+                if (bundle_exists == false) {
+                        //New bundle, add the AMF the node and save in the 
single step
+                        SmfPlmExecEnv plm;
+                        plm.setAmfNode(const_cast<std::string 
&>(i_oldStep->getSwNode()));
+                        (*oldStepBundleIter).addPlmExecEnv(plm);
+                        LOG_NO("New Bundle = %s added, AmfNode = %s", 
(*oldStepBundleIter).getBundleDn().c_str()  ,plm.getAmfNode().c_str());
+                        io_newStep->addSwAdd((*oldStepBundleIter));
+                }
+        }
+
+        LOG_NO("Merge SwRemoveLists from the rolling steps into a single step 
bundle list");
+        bundlesOldStep = i_oldStep->getSwRemoveList();
+        for (oldStepBundleIter = bundlesOldStep.begin(); oldStepBundleIter != 
bundlesOldStep.end(); oldStepBundleIter++) {
+                //Read the list of already saved bundles, if already exist 
only add the new
+                //swNode to the existing bundle
+                std::list < SmfBundleRef >::iterator newStepBundleIter;
+                std::list < SmfBundleRef > & bundlesNewStep = 
io_newStep->getSwRemoveList();
+                //Check if bundle already saved
+                bool bundle_exists = false;
+                for (newStepBundleIter = bundlesNewStep.begin(); 
newStepBundleIter != bundlesNewStep.end(); newStepBundleIter++) {
+                        if ((*newStepBundleIter).getBundleDn() == 
(*oldStepBundleIter).getBundleDn()) {
+                                //Bundle already saved in the single step, 
just add the AMF the node
+                                SmfPlmExecEnv plm;
+                                plm.setAmfNode(const_cast<std::string 
&>(i_oldStep->getSwNode()));
+                                (*newStepBundleIter).addPlmExecEnv(plm);
+                                bundle_exists = true;
+                                LOG_NO("Existing Bundle = %s, AmfNode = %s", 
(*oldStepBundleIter).getBundleDn().c_str()  ,plm.getAmfNode().c_str());
+                        } 
+                }
+
+                if (bundle_exists == false) {
+                        //New bundle, add the AMF the node and save in the 
single step
+                        SmfPlmExecEnv plm;
+                        plm.setAmfNode(const_cast<std::string 
&>(i_oldStep->getSwNode()));
+                        (*oldStepBundleIter).addPlmExecEnv(plm);
+                        LOG_NO("New Bundle = %s added, AmfNode = %s", 
(*oldStepBundleIter).getBundleDn().c_str()  ,plm.getAmfNode().c_str());
+                        io_newStep->addSwRemove((*oldStepBundleIter));
+                }
+        }
+       TRACE_LEAVE();
+        return true;
+}
+
+//------------------------------------------------------------------------------
 // calculateNodeList()
 
//------------------------------------------------------------------------------
 bool 
@@ -2263,22 +2758,26 @@ SaAisErrorT
 SmfUpgradeProcedure::getImmSteps()
 {
        SaAisErrorT rc = SA_AIS_OK;
-
        TRACE_ENTER();
-
        SmfUpgradeMethod *upgradeMethod = getUpgradeMethod();
        if (upgradeMethod == NULL) {
                LOG_NO("SmfUpgradeProcedure::getImmSteps: no upgrade method 
found");
                TRACE_LEAVE();
                return SA_AIS_ERR_NOT_EXIST;
        }
-                       
+
        if (upgradeMethod->getUpgradeMethod() == SA_SMF_ROLLING) {
                TRACE("Rolling upgrade");
                rc = getImmStepsRolling();
        } else if (upgradeMethod->getUpgradeMethod() == SA_SMF_SINGLE_STEP) {
-               TRACE("Single step upgrade");
-               rc = getImmStepsSingleStep();
+                if 
(SmfCampaignThread::instance()->campaign()->getUpgradeCampaign()->getProcExecutionMode()
+                   == SMF_MERGE_TO_SINGLE_STEP) {  //This is a merged single 
step
+                        TRACE("Merged single step upgrade");
+                        rc = getImmStepsMergedSingleStep();
+                } else { //This is a written normal single step
+                        TRACE("Single step upgrade");
+                        rc = getImmStepsSingleStep();
+                }
        } else {
                LOG_NO("SmfUpgradeProcedure::getImmSteps: no upgrade method 
type found");
                rc =  SA_AIS_ERR_NOT_EXIST;
@@ -2336,7 +2835,8 @@ SmfUpgradeProcedure::getImmStepsRolling(
 
                TRACE("Fetch IMM data for item in stepList");
 
-               SmfUpgradeStep *newStep = new SmfUpgradeStep();
+               SmfUpgradeStep *newStep = new(std::nothrow) SmfUpgradeStep;
+                osafassert(newStep != NULL);
 
                if (newStep->init((const SaImmAttrValuesT_2 **)attributes) != 
SA_AIS_OK) {
                        LOG_NO("SmfUpgradeProcedure::getImmStepsRolling: 
Initialization failed for step %s", (*stepit).c_str());
@@ -2448,7 +2948,8 @@ SmfUpgradeProcedure::getImmStepsSingleSt
 
        TRACE("Fetch IMM data for item in stepList");
 
-       SmfUpgradeStep *newStep = new SmfUpgradeStep();
+       SmfUpgradeStep *newStep = new(std::nothrow) SmfUpgradeStep;
+        osafassert(newStep != NULL);
 
        if (newStep->init((const SaImmAttrValuesT_2 **)attributes) != 
SA_AIS_OK) {
                LOG_NO("SmfUpgradeProcedure::getImmStepsSingleStep: 
Initialization failed for step %s", (*stepit).c_str());
@@ -2474,7 +2975,7 @@ SmfUpgradeProcedure::getImmStepsSingleSt
        // about e.g. pathNamePrefix.
        // Fetch it from the campaign XML data.
        //---------------------------------------------
-       const SmfUpgradeScope* scope        = upgradeMethod->getUpgradeScope(); 
;
+       const SmfUpgradeScope* scope        = upgradeMethod->getUpgradeScope();
        const SmfForAddRemove* forAddRemove = dynamic_cast<const 
SmfForAddRemove*>(scope);
        const SmfForModify*    forModify    = dynamic_cast<const 
SmfForModify*>(scope);
 
@@ -2540,6 +3041,117 @@ SmfUpgradeProcedure::getImmStepsSingleSt
 }
 
 
//------------------------------------------------------------------------------
+// getImmStepsMergedSingleStep()
+//------------------------------------------------------------------------------
+SaAisErrorT 
+SmfUpgradeProcedure::getImmStepsMergedSingleStep()
+{
+        // This routine will never be executed unless the campaign procedures 
is merged into
+        // a single step procedure i.e. the merge is configured in SMF.
+        // If above is valid, there is only in two cases this routine will be 
executed
+        // 1) after a si-swap, step state is SA_SMF_STEP_INITIAL
+        // 2) after a cluster reboot, step state is SA_SMF_STEP_EXECUTING
+        //
+        // The IMM modifications are always made before the reboot. The only 
thing left to
+        // do after the reboot is unlock DU, online remove of bundles and 
callbacks.
+        // This infon is fetched from IMM and campaign without recalculation 
of steps.
+        //
+        // After a si-swap, the procedure was never started before the swap. 
Just do the merge
+        // again on this new active SC.
+
+       SmfImmUtils immutil;
+       SaImmAttrValuesT_2 **attributes;
+       std::list < std::string > stepList;
+
+       TRACE_ENTER();
+       SmfUpgradeStep *newStep = new(std::nothrow) SmfUpgradeStep;
+        osafassert(newStep != NULL);
+
+       // Read the single step from IMM
+       if (immutil.getChildren(getDn(), stepList, SA_IMM_SUBLEVEL, 
"SaSmfStep") == false) {
+               LOG_NO("SmfUpgradeProcedure::getImmStepsMergedSingleStep: 
Failed to get steps for procedure %s", getDn().c_str());
+               TRACE_LEAVE();
+               return SA_AIS_ERR_NOT_EXIST;
+       }
+
+       TRACE("Fetch IMM data for merged upgrade procedure step");
+       std::list < std::string >::iterator stepit;
+       /* Fetch IMM data for our upgrade procedure single step, only just one 
*/
+       stepit = stepList.begin();
+       if (immutil.getObject((*stepit), &attributes) == false) {
+               LOG_NO("SmfUpgradeProcedure::getImmStepsMergedSingleStep: IMM 
data for step %s not found", (*stepit).c_str());
+               TRACE_LEAVE();
+               return SA_AIS_ERR_NOT_EXIST;
+       }
+
+       TRACE("Copy step basic data from IMM into the new merged step.");
+       if (newStep->init((const SaImmAttrValuesT_2 **)attributes) != 
SA_AIS_OK) {
+               LOG_NO("SmfUpgradeProcedure::getImmStepsMergedSingleStep: 
Initialization failed for step %s", (*stepit).c_str());
+               delete newStep;
+               TRACE_LEAVE();
+               return SA_AIS_ERR_INIT;
+       }
+
+       if ((newStep->getState() != SA_SMF_STEP_INITIAL) && 
(newStep->getState() != SA_SMF_STEP_EXECUTING)) {
+               LOG_NO("SmfUpgradeProcedure::getImmStepsMergedSingleStep: 
Invalid state %d", newStep->getState());
+                delete newStep;
+                TRACE_LEAVE();
+                return SA_AIS_ERR_INIT;
+       }
+
+        newStep->setDn((*stepit));
+       newStep->setProcedure(this);
+
+        if(newStep->getState() == SA_SMF_STEP_INITIAL) {
+                mergeStepIntoSingleStep(this, newStep); //Just merge again, as 
before si-swap
+               addProcStep(newStep);
+        } else if(newStep->getState() == SA_SMF_STEP_EXECUTING) {
+                //Fetch AU/DU and step swNode from IMM steps
+                SaAisErrorT rc = readCampaignImmModel(newStep);
+                if (rc != SA_AIS_OK) {
+                        
LOG_NO("SmfUpgradeProcedure::getImmStepsMergedSingleStep: Fail to read campaign 
IMM model");
+                        delete newStep;
+                        TRACE_LEAVE();
+                        return rc;
+                }
+
+               //Fetch bundle info from IMM steps, create SmfBundleRef and add 
pathnamePrefix to step
+               rc = bundleRefFromSsCampaignImmModel(newStep);
+                if (rc != SA_AIS_OK) {
+                        
LOG_NO("SmfUpgradeProcedure::getImmStepsMergedSingleStep: Fail to create 
SmfBundleRef");
+                        delete newStep;
+                        TRACE_LEAVE();
+                        return rc;
+                }
+
+               //Add the recreated step to the procedure
+               addProcStep(newStep);
+
+               //Fetch callbacks and procedure init/wraup actions.
+               SmfUpgradeCampaign * camp = 
SmfCampaignThread::instance()->campaign()->getUpgradeCampaign();
+               const std::vector < SmfUpgradeProcedure * >& procedures = 
camp->getProcedures();
+               std::vector < SmfUpgradeProcedure * >::const_iterator proc_iter;
+               for (proc_iter = procedures.begin(); proc_iter != 
procedures.end(); proc_iter++) {
+                       
LOG_NO("SmfUpgradeProcedure::getImmStepsMergedSingleStep: Fetch callbacks and 
wrapup actions from  [%s]", (*proc_iter)->getName().c_str());
+
+                       //The init actions
+                       LOG_NO("Copy the procedure init actions");
+                       addInitActions((*proc_iter)->getInitActions());
+
+                       //The wrapup actions
+                       LOG_NO("Copy the procedure wrapup actions");
+                       addWrapupActions((*proc_iter)->getWrapupActions());
+
+                       //The callbacks
+                       getCallbackList((*proc_iter)->getUpgradeMethod());
+               }
+        }
+
+       TRACE_LEAVE();
+       return SA_AIS_OK;
+}
+
+//------------------------------------------------------------------------------
 // readCampaignImmModel()
 
//------------------------------------------------------------------------------
 SaAisErrorT
@@ -2559,7 +3171,7 @@ SmfUpgradeProcedure::readCampaignImmMode
        TRACE("Read the SaSmfActivationUnit object from IMM parent=%s", 
i_newStep->getDn().c_str());
        if (immutil.getChildren(i_newStep->getDn(), auList, SA_IMM_SUBLEVEL, 
"SaSmfActivationUnit") != false) {
                TRACE("SaSmfActivationUnit:Resulting list size=%zu", 
auList.size());
-               
+
                //Continue only if there really is any SaSmfActivationUnit.
                //If there was no match for the types to operate on e.g. 
component or SU type, 
                //when the step was calculated, no SaSmfActivationUnit was 
created.
@@ -2623,8 +3235,10 @@ SmfUpgradeProcedure::readCampaignImmMode
                                                const SaNameT * saSmfINNode;
                                                for(ix = 0; (saSmfINNode = 
immutil_getNameAttr((const SaImmAttrValuesT_2 **)attributes, 
                                                                                
               "saSmfINNode", ix)) != NULL; ix++) {
-                                                       TRACE("Single step 
saSmfINNode->value = %s (%u)", osaf_extended_name_borrow(saSmfINNode), ix);
-                                                       
i_newStep->addSwNode(osaf_extended_name_borrow(saSmfINNode));
+                                                       TRACE("Single step 
saSmfINNode->value = %s (%u)",
+                                                              
osaf_extended_name_borrow(saSmfINNode), ix);
+
+                                                        
i_newStep->addSwNode(osaf_extended_name_borrow(saSmfINNode));
                                                }
                                                if ( ix == 0 ) {
                                                        
LOG_NO("SmfUpgradeProcedure::readCampaignImmModel: saSmfINNode does not 
exist");  
@@ -2734,6 +3348,283 @@ SmfUpgradeProcedure::readCampaignImmMode
 }
 
 
//------------------------------------------------------------------------------
+// bundleRefFromSsCampaignImmModel()
+//------------------------------------------------------------------------------
+SaAisErrorT
+SmfUpgradeProcedure::bundleRefFromSsCampaignImmModel(SmfUpgradeStep *i_newStep)
+{
+        TRACE_ENTER();
+       std::list < std::string > auList;
+       std::list < std::string > duList;
+       std::list < std::string >::iterator stringIt;
+       unsigned int ix;
+       SmfImmUtils immutil;
+       SaImmAttrValuesT_2 **attributes;
+
+        //This method create lists of SmfBundleRef from a single step campaign 
IMM model.
+        //-From activationUnit the bundles to install are fetched.
+        //-From deactivationUnit the bundles to remove are fetched.
+        //-plmExecEnv are filled in from nodes found in the resp. 
SaSmfImageNodes
+        //-pathNamePrefix is fetched from the parsed camaign.
+
+       //----------------------------------------------------------------
+       // Read the pathNamePrefix (SmfBundleRef) from the parsed campaign
+       //----------------------------------------------------------------
+       //Read all the bundles to add/remove from the parsed camaign
+        SmfUpgradeCampaign * camp = 
SmfCampaignThread::instance()->campaign()->getUpgradeCampaign();
+       const std::vector < SmfUpgradeProcedure * >& procedures = 
camp->getProcedures();
+       std::vector < SmfUpgradeProcedure * >::const_iterator proc_iter;
+       std::list < SmfBundleRef > bundlesOldProcSS;
+       std::list < SmfBundleRef *> bundlesOldProcRO;
+       for (proc_iter = procedures.begin(); proc_iter != procedures.end(); 
proc_iter++) {
+               if ((*proc_iter)->getUpgradeMethod()->getUpgradeMethod() == 
SA_SMF_ROLLING) { //SA_SMF_ROLLING
+                       const SmfByTemplate *byTemplate = 
(SmfByTemplate*)(*proc_iter)->getUpgradeMethod()->getUpgradeScope();
+                       if (byTemplate != NULL) {
+                               bundlesOldProcRO.insert(bundlesOldProcRO.end(),
+                                                       
byTemplate->getTargetNodeTemplate()->getSwInstallList().begin(),
+                                                       
byTemplate->getTargetNodeTemplate()->getSwInstallList().end());
+
+                               bundlesOldProcRO.insert(bundlesOldProcRO.end(),
+                                                       
byTemplate->getTargetNodeTemplate()->getSwRemoveList().begin(),
+                                                       
byTemplate->getTargetNodeTemplate()->getSwRemoveList().end());
+                       } else {
+                               
LOG_NO("SmfUpgradeProcedure::bundleRefFromSsCampaignImmModel: Procedure scope 
not found (byTemplate)");
+                       }
+               } else { //SA_SMF_SINGLE_STEP
+                       const SmfForAddRemove* addRemove = dynamic_cast<const 
SmfForAddRemove*>((*proc_iter)->getUpgradeMethod()->getUpgradeScope());
+                       const SmfForModify* modify = dynamic_cast<const 
SmfForModify*>((*proc_iter)->getUpgradeMethod()->getUpgradeScope());
+                       if (addRemove != NULL) {
+                               bundlesOldProcSS.insert(bundlesOldProcSS.end(),
+                                                       
addRemove->getActivationUnit()->getSwAdd().begin(),
+                                                       
addRemove->getActivationUnit()->getSwAdd().end());
+
+                               bundlesOldProcSS.insert(bundlesOldProcSS.end(),
+                                                       
addRemove->getDeactivationUnit()->getSwRemove().begin(),
+                                                       
addRemove->getDeactivationUnit()->getSwRemove().end());
+                       } else if (modify != NULL) {
+                               bundlesOldProcSS.insert(bundlesOldProcSS.end(),
+                                                       
modify->getActivationUnit()->getSwAdd().begin(),
+                                                       
modify->getActivationUnit()->getSwAdd().end());
+
+                               bundlesOldProcSS.insert(bundlesOldProcSS.end(),
+                                                       
modify->getActivationUnit()->getSwRemove().begin(),
+                                                       
modify->getActivationUnit()->getSwRemove().end());
+                       } else {
+                               
LOG_NO("SmfUpgradeProcedure::bundleRefFromSsCampaignImmModel: Procedure scope 
not found (forAddRemove/forModify)");
+                       }
+               }
+       }
+
+       //---------------------------------------------
+       // Read the SaSmfActivationUnit object from IMM
+       //---------------------------------------------
+       TRACE("Read the SaSmfActivationUnit object from IMM parent=%s", 
i_newStep->getDn().c_str());
+       if (immutil.getChildren(i_newStep->getDn(), auList, SA_IMM_SUBLEVEL, 
"SaSmfActivationUnit") != false) {
+                TRACE("SaSmfActivationUnit:Resulting list size=%zu", 
auList.size());
+
+               //Continue if a SaSmfActivationUnit exist.
+               if (auList.size() != 0) {
+
+                        // Fetch IMM data for SaSmfAactivationUnit (should be 
max one)
+                        std::string activationUnit = (*auList.begin());
+                        if (immutil.getObject(activationUnit, &attributes) == 
false) {
+                               
LOG_NO("SmfUpgradeProcedure::bundleRefFromSsCampaignImmModel: IMM data for step 
activationUnit %s not found",
+                                       activationUnit.c_str());
+                               TRACE_LEAVE();
+                               return SA_AIS_ERR_NOT_EXIST;
+                       }
+
+                       //For the SaAmfActivationUnit fetch the SaSmfImageNodes 
objects
+                       TRACE("For the SaAmfActivationUnit fetch the 
SaSmfImageNodes objects");
+                       std::list < std::string > imageNodesList;
+                       if (immutil.getChildren(activationUnit, imageNodesList, 
SA_IMM_SUBLEVEL, "SaSmfImageNodes") != false) {
+                               TRACE("Nr of SaSmfImageNodes found = %zu", 
imageNodesList.size());
+
+                               //For all SaSmfImageNodes.(Bundles may be 
installed on different nodes)
+                               for (stringIt = imageNodesList.begin(); 
stringIt != imageNodesList.end(); stringIt++) {
+                                       //TRACE("std::string imageNodes = %s", 
(*stringIt).c_str());
+                                       if (immutil.getObject((*stringIt), 
&attributes) == false) {
+                                               
LOG_NO("SmfUpgradeProcedure::bundleRefFromSsCampaignImmModel: IMM data for 
ImageNodes %s not found",
+                                                      (*stringIt).c_str());
+                                               TRACE_LEAVE();
+                                               return SA_AIS_ERR_NOT_EXIST;
+                                       }
+
+                                       // Read the saSmfINSwNode attribute, 
may contain several nodes
+                                       // SaSmfImageNodes Single step may 
contain several nodes
+                                       const SaNameT * saSmfINNode;
+                                       const SaNameT * saSmfINSwBundle;
+                                       SmfBundleRef tmpBundleRef; 
//addPlmExecEnv setBundleDn setPathNamePrefix
+                                       saSmfINSwBundle = 
immutil_getNameAttr((const SaImmAttrValuesT_2 **)attributes, "saSmfINSwBundle", 
0);
+                                       
tmpBundleRef.setBundleDn(osaf_extended_name_borrow(saSmfINSwBundle));
+
+                                       for(ix = 0; (saSmfINNode = 
immutil_getNameAttr((const SaImmAttrValuesT_2 **)attributes, 
+                                                                               
       "saSmfINNode", ix)) != NULL; ix++) {
+                                               TRACE("Single step 
saSmfINNode->value = %s (%u)",
+                                                     
osaf_extended_name_borrow(saSmfINNode), ix);
+
+                                               SmfPlmExecEnv plm;
+                                               std::string 
amfNode(osaf_extended_name_borrow(saSmfINNode));
+                                               plm.setAmfNode(amfNode);
+                                               //Add the new SmfPlmExecEnv 
into the bundle plvExecEnv list
+                                               tmpBundleRef.addPlmExecEnv(plm);
+                                       }
+
+                                       if ( ix == 0 ) {
+                                               
LOG_NO("SmfUpgradeProcedure::bundleRefFromSsCampaignImmModel: saSmfINNode does 
not exist");
+                                               TRACE_LEAVE();
+                                               return SA_AIS_ERR_NOT_EXIST;
+                                       }
+
+                                       //Search for pathnamePrefix search all 
the procedures in the parsed campaign
+                                       //It is assumed the pathnamePrefix is 
common on all nodes for a spcific bundle name.
+                                       std::list < SmfBundleRef >::iterator 
bundle_iter;        //For SS procedures
+                                       std::list < SmfBundleRef * >::iterator 
bundlePtr_iter;   //For RO procedures
+
+                                       bool pathNamePrefixFound = false;
+                                       //Look in rolling procedures
+                                       for(bundlePtr_iter = 
bundlesOldProcRO.begin(); bundlePtr_iter != bundlesOldProcRO.end(); 
bundlePtr_iter++) {
+                                               
if((*bundlePtr_iter)->getBundleDn() == tmpBundleRef.getBundleDn()) {
+                                                       
tmpBundleRef.setPathNamePrefix((*bundlePtr_iter)->getPathNamePrefix());
+                                                       pathNamePrefixFound = 
true;
+                                                       
LOG_NO("SmfUpgradeProcedure::bundleRefFromSsCampaignImmModel: pathnamePrefix 
[%s] for bundle [%s] found", 
+                                                              
tmpBundleRef.getPathNamePrefix().c_str(), 
+                                                              
tmpBundleRef.getBundleDn().c_str());
+                                                       break;
+                                               }
+                                       }
+
+                                       if (pathNamePrefixFound == false) {
+                                               //If not found also look in 
single step procedures
+                                               for(bundle_iter = 
bundlesOldProcSS.begin(); bundle_iter != bundlesOldProcSS.end(); bundle_iter++) 
{
+                                                       
if((*bundle_iter).getBundleDn() == tmpBundleRef.getBundleDn()) {
+                                                               
tmpBundleRef.setPathNamePrefix((*bundle_iter).getPathNamePrefix());
+                                                               
pathNamePrefixFound = true;
+                                                               
LOG_NO("SmfUpgradeProcedure::bundleRefFromSsCampaignImmModel: pathnamePrefix 
[%s] for bundle [%s] found", 
+                                                                      
tmpBundleRef.getPathNamePrefix().c_str(), 
+                                                                      
tmpBundleRef.getBundleDn().c_str());
+                                                               break;
+                                                       }
+                                               }
+                                       }
+
+                                       if ( pathNamePrefixFound == false ) {
+                                               
LOG_NO("SmfUpgradeProcedure::bundleRefFromSsCampaignImmModel: 
pathNamePrefixFound not found");
+                                               TRACE_LEAVE();
+                                               return SA_AIS_ERR_NOT_EXIST;
+                                       }
+
+                                       //Add the new bundle to add to the step
+                                       i_newStep->addSwAdd(tmpBundleRef);
+                               } //for
+                        } //!= false
+                } //if (auList.size() != 0)
+        }
+
+       //---------------------------------------------
+       // Read the SaSmfDeactivationUnit object from IMM
+       //---------------------------------------------
+       TRACE("Read the SaSmfActivationUnit object from IMM parent=%s", 
i_newStep->getDn().c_str());
+       if (immutil.getChildren(i_newStep->getDn(), duList, SA_IMM_SUBLEVEL, 
"SaSmfDeactivationUnit") != false) {
+                TRACE("SaSmfDeactivationUnit:Resulting list size=%zu", 
duList.size());
+
+               //Continue if a SaSmfDeactivationUnit exist.
+               if (duList.size() != 0) {
+
+                        // Fetch IMM data for SaSmfDeactivationUnit (should be 
max one)
+                        std::string activationUnit = (*duList.begin());
+                        if (immutil.getObject(activationUnit, &attributes) == 
false) {
+                               
LOG_NO("SmfUpgradeProcedure::bundleRefFromSsCampaignImmModel: IMM data for step 
activationUnit %s not found",
+                                       activationUnit.c_str());
+                               TRACE_LEAVE();
+                               return SA_AIS_ERR_NOT_EXIST;
+                       }
+
+                       //For the SaSmfDeactivationUnit fetch the 
SaSmfImageNodes objects
+                       TRACE("For the SaSmfDeactivationUnit fetch the 
SaSmfImageNodes objects");
+                       std::list < std::string > imageNodesList;
+                       if (immutil.getChildren(activationUnit, imageNodesList, 
SA_IMM_SUBLEVEL, "SaSmfImageNodes") != false) {
+                               TRACE("Nr of SaSmfImageNodes found = %zu", 
imageNodesList.size());
+
+                               //For all SaSmfImageNodes.(Bundles may be 
installed on different nodes)
+                               for (stringIt = imageNodesList.begin(); 
stringIt != imageNodesList.end(); stringIt++) {
+                                       //TRACE("std::string imageNodes = %s", 
(*stringIt).c_str());
+                                       if (immutil.getObject((*stringIt), 
&attributes) == false) {
+                                               
LOG_NO("SmfUpgradeProcedure::bundleRefFromSsCampaignImmModel: IMM data for 
ImageNodes %s not found",
+                                                      (*stringIt).c_str());
+                                               TRACE_LEAVE();
+                                               return SA_AIS_ERR_NOT_EXIST;
+                                       }
+
+                                       //saSmfINSwBundle
+                                       // Read the saSmfINSwNode attribute, 
may contain several nodes
+                                       // SaSmfImageNodes Single step may 
contain several nodes
+                                       const SaNameT * saSmfINNode;
+                                       const SaNameT * saSmfINSwBundle;
+                                       SmfBundleRef tmpBundleRef; 
//addPlmExecEnv setBundleDn setPathNamePrefix
+                                       saSmfINSwBundle = 
immutil_getNameAttr((const SaImmAttrValuesT_2 **)attributes, "saSmfINSwBundle", 
0);
+                                       
tmpBundleRef.setBundleDn(osaf_extended_name_borrow(saSmfINSwBundle));
+
+                                       for(ix = 0; (saSmfINNode = 
immutil_getNameAttr((const SaImmAttrValuesT_2 **)attributes, 
+                                                                               
       "saSmfINNode", ix)) != NULL; ix++) {
+                                               TRACE("Single step 
saSmfINNode->value = %s (%u)",
+                                                     
osaf_extended_name_borrow(saSmfINNode), ix);
+
+                                               SmfPlmExecEnv plm;
+                                               std::string 
amfNode(osaf_extended_name_borrow(saSmfINNode));
+                                               plm.setAmfNode(amfNode);
+                                               //Add the new SmfPlmExecEnv 
into the bundle plvExecEnv list
+                                               tmpBundleRef.addPlmExecEnv(plm);
+                                       }
+
+                                       if ( ix == 0 ) {
+                                               
LOG_NO("SmfUpgradeProcedure::bundleRefFromSsCampaignImmModel: saSmfINNode does 
not exist");
+                                               TRACE_LEAVE();
+                                               return SA_AIS_ERR_NOT_EXIST;
+                                       }
+
+                                       //Search for pathnamePrefix search all 
the procedures in the parsed campaign
+                                       //It is assumed the pathnamePrefix is 
common on all nodes for a spcific bundle name.
+                                       std::list < SmfBundleRef >::iterator 
bundle_iter;        //For SS procedures
+                                       std::list < SmfBundleRef * >::iterator 
bundlePtr_iter;   //For RO procedures
+
+                                       bool pathNamePrefixFound = false;
+                                       //Look in rolling procedures
+                                       for(bundlePtr_iter = 
bundlesOldProcRO.begin(); bundlePtr_iter != bundlesOldProcRO.end(); 
bundlePtr_iter++) {
+                                               
if((*bundlePtr_iter)->getBundleDn() == tmpBundleRef.getBundleDn()) {
+                                                       
tmpBundleRef.setPathNamePrefix((*bundlePtr_iter)->getPathNamePrefix());
+                                                       pathNamePrefixFound = 
true;
+                                               }
+                                       }
+
+                                       if (pathNamePrefixFound == false) {
+                                               //If not found also look in 
single step procedures
+                                               for(bundle_iter = 
bundlesOldProcSS.begin(); bundle_iter != bundlesOldProcSS.end(); bundle_iter++) 
{
+                                                       
if((*bundle_iter).getBundleDn() == tmpBundleRef.getBundleDn()) {
+                                                               
tmpBundleRef.setPathNamePrefix((*bundle_iter).getPathNamePrefix());
+                                                               
pathNamePrefixFound = true;
+                                                       }
+                                               }
+                                       }
+
+                                       if ( pathNamePrefixFound == false ) {
+                                               
LOG_NO("SmfUpgradeProcedure::bundleRefFromSsCampaignImmModel: 
pathNamePrefixFound not found");
+                                               TRACE_LEAVE();
+                                               return SA_AIS_ERR_NOT_EXIST;
+                                       }
+
+                                       //Add the new bundle to add to the step
+                                       i_newStep->addSwRemove(tmpBundleRef);
+                               } //for
+                        } //!= false
+                } //if (duList.size() != 0)
+        }
+
+       TRACE_LEAVE();
+       return SA_AIS_OK;
+}
+
+//------------------------------------------------------------------------------
 // setEntitiesToAddRemMod()
 
//------------------------------------------------------------------------------
 bool
@@ -2780,7 +3671,7 @@ SmfUpgradeProcedure::setEntitiesToAddRem
                                         break;
                                 }
                         }
-                        
+
                         immUtil.classDescriptionMemoryFree(attrDefinitionsOut);
 
                         //Find attribute name in SmfImmCreateOperation 
attributes
@@ -2875,7 +3766,7 @@ bool SmfUpgradeProcedure::isCompRestarta
        //Evaluate the component restart information found above
        if (instanceCompDisableRestartIsSet == false){
                //No info in instance, check if component type 
saAmfCtDefDisableRestart is set in base class
-               if ((instanceCtDefDisableRestartIsSet == true) && 
+               if ((instanceCtDefDisableRestartIsSet == true) &&
                    (instanceCtDefDisableRestart == SA_TRUE)){ //Types says non 
restartable
                        TRACE("saSmfStepRestartOption is set to true(1), but 
the component %s is not restartable according to base type information", 
i_compDN.c_str()); 
                        rc = false;
@@ -2896,7 +3787,7 @@ done:
 // getActDeactUnitsAndNodes()
 
//------------------------------------------------------------------------------
 bool 
-SmfUpgradeProcedure::getActDeactUnitsAndNodes(const std::string &i_dn, 
std::string& io_unit, 
+SmfUpgradeProcedure::getActDeactUnitsAndNodes(const std::string &i_dn, 
std::string& io_unit,
                                              std::string& io_node,
                                              std::multimap<std::string, 
objectInst> &i_objects)
 {
diff --git a/osaf/services/saf/smfsv/smfd/SmfUpgradeProcedure.hh 
b/osaf/services/saf/smfsv/smfd/SmfUpgradeProcedure.hh
--- a/osaf/services/saf/smfsv/smfd/SmfUpgradeProcedure.hh
+++ b/osaf/services/saf/smfsv/smfd/SmfUpgradeProcedure.hh
@@ -205,6 +205,13 @@ class SmfUpgradeProcedure {
        const std::string & getDn();
 
 ///
+/// Purpose:  Get the name of the procedure
+/// @param    None
+/// @return   A std::string containing the name of the procedure.
+///
+       const std::string & getName() { return m_name; };
+
+///
 /// Purpose:  Set the state in IMM procedure object and send state change 
notification
 /// @param    i_state The SaSmfProcStateT to set.
 /// @return   None.
@@ -308,6 +315,7 @@ class SmfUpgradeProcedure {
 /// @return   True if successful otherwise false
 ///
        bool calculateSteps();
+       bool calculateSteps(std::multimap<std::string, objectInst> &i_objects);
 
 ///
 /// Purpose:  Calculate upgrade steps for rolling upgrade
@@ -326,6 +334,31 @@ class SmfUpgradeProcedure {
                                 std::multimap<std::string, objectInst> 
&i_objects);
 
 ///
+/// Purpose:  Merge procedure steps into a single-step
+/// @param    i_proc A SmfUpgradeProcedure* pointing to the procedure
+/// @return   None.
+///
+        bool mergeStepIntoSingleStep(SmfUpgradeProcedure * i_proc, 
SmfUpgradeStep *i_newStep = 0);
+
+///
+/// Purpose:  Merge merge existing single-step bundle ref into a new 
single-step
+/// @param    io_newStep a SmfUpgradeStep * pointion to the new step
+/// @param    i_oldStep a SmfUpgradeStep * pointion to the step to copy from
+/// @return   None.
+///
+        bool mergeBundleRefSingleStepToSingleStep(SmfUpgradeStep * io_newStep,
+                                                 SmfUpgradeStep * i_oldStep);
+
+///
+/// Purpose:  Merge merge existing step (rolling) bundle ref into a new 
single-step
+/// @param    io_newStep a SmfUpgradeStep * pointion to the new step
+/// @param    i_oldStep a SmfUpgradeStep * pointion to the step to copy from
+/// @return   None.
+///
+       bool mergeBundleRefRollingToSingleStep(SmfUpgradeStep * io_newStep,
+                                               SmfUpgradeStep * i_oldStep);
+
+///
 /// Purpose:  Calculate list of nodes from objectDn
 /// @param    i_objectDn A DN to a cluster or node group.
 /// @param    o_nodeList The resulting list of nodes.
@@ -485,12 +518,26 @@ class SmfUpgradeProcedure {
        SaAisErrorT getImmStepsSingleStep();
 
 ///
+/// Purpose:  Get procedure steps for merged Single step upgrade
+/// @param    -
+/// @return   -
+///
+       SaAisErrorT getImmStepsMergedSingleStep();
+
+///
 /// Purpose:  Read campaign data from IMM and store the information in 
i_newStep
 /// @param    -
 /// @return   -
 ///
        SaAisErrorT readCampaignImmModel(SmfUpgradeStep * i_newStep);
 
+  ///
+/// Purpose:  Create lists of SmfBundleRef from a single step campaign IMM 
model.
+/// @param    -
+/// @return   -
+///
+       SaAisErrorT bundleRefFromSsCampaignImmModel(SmfUpgradeStep * i_newStep);
+
 ///
 /// Purpose:  Register the DNs of the added, removed or modified objects in 
the step
 /// @param    i_step The SmfUpgradeStep from where to read the modifications
@@ -507,6 +554,15 @@ class SmfUpgradeProcedure {
         const std::vector < SmfUpgradeStep * >& getProcSteps() { return 
m_procSteps; }
 
 ///
+/// Purpose:  Add the list of upgrade steps
+/// @param    The list of upgrade steps to add
+/// @return   none
+///
+        void addProcSteps(const std::vector < SmfUpgradeStep * >& i_procSteps)
+                { m_procSteps.insert(m_procSteps.end(),
+                                     i_procSteps.begin(),
+                                     i_procSteps.end()); }
+///
 /// Purpose:  Get the list of init actions
 /// @param    -
 /// @return   The list of init actions.
@@ -514,6 +570,16 @@ class SmfUpgradeProcedure {
         const std::vector < SmfUpgradeAction * >& getInitActions() { return 
m_procInitAction; }
 
 ///
+/// Purpose:  Add a list of init actions
+/// @param    The list of init actions to add
+/// @return   none
+///
+        void addInitActions(const std::vector < SmfUpgradeAction * >& 
i_initActions)
+                { m_procInitAction.insert(m_procInitAction.end(),
+                                          i_initActions.begin(),
+                                          i_initActions.end()); }
+
+///
 /// Purpose:  Get the list of wrapup actions
 /// @param    -
 /// @return   The list of wrapup actions.
@@ -521,6 +587,16 @@ class SmfUpgradeProcedure {
         const std::vector < SmfUpgradeAction * >& getWrapupActions() { return 
m_procWrapupAction; }
 
 ///
+/// Purpose:  Add the list of wrapup actions
+/// @param    The list of wrapup actions to add
+/// @return   none
+///
+        void  addWrapupActions(const std::vector < SmfUpgradeAction * >& 
i_wrapupActions)
+                { m_procWrapupAction.insert(m_procWrapupAction.end(),
+                                            i_wrapupActions.begin(),
+                                            i_wrapupActions.end()); }
+
+///
 /// Purpose:  Check if the component pointed out by DN is restartable
 /// @param    i_compDN The DN of the components
 /// @return   True if restartable otherwise false.
@@ -546,6 +622,16 @@ class SmfUpgradeProcedure {
         std::list < SmfCallback * >& getCbksBeforeLock() { return 
m_beforeLock; }
 
 ///
+/// Purpose:  Add the list of before lock callbacks
+/// @param    The list of  before lock callbacks to add
+/// @return   none
+///
+        void  addCbksBeforeLock(const std::list < SmfCallback * >& 
i_beforeLock)
+                { m_beforeLock.insert(m_beforeLock.end(),
+                                      i_beforeLock.begin(),
+                                      i_beforeLock.end()); }
+
+///
 /// Purpose:  Get the list of callbacks beforeTerm
 /// @param    -
 /// @return   The list of callbacks.
@@ -553,6 +639,16 @@ class SmfUpgradeProcedure {
         std::list < SmfCallback * >& getCbksBeforeTerm() { return 
m_beforeTerm; }
 
 ///
+/// Purpose:  Add the list of before term callbacks
+/// @param    The list of  before term callbacks to add
+/// @return   none
+///
+        void  addCbksBeforeTerm(const std::list < SmfCallback * >& 
i_beforeTerm)
+                { m_beforeTerm.insert(m_beforeTerm.end(),
+                                      i_beforeTerm.begin(),
+                                      i_beforeTerm.end()); }
+
+///
 /// Purpose:  Get the list of callbacks afterImmModify
 /// @param    -
 /// @return   The list of callbacks.
@@ -560,6 +656,16 @@ class SmfUpgradeProcedure {
         std::list < SmfCallback * >& getCbksAfterImmModify() { return 
m_afterImmModify; }
 
 ///
+/// Purpose:  Add the list of before term callbacks
+/// @param    The list of before term callbacks to add
+/// @return   none
+///
+        void  addCbksAfterImmModify(const std::list < SmfCallback * >& 
i_afterImmModify)
+                { m_afterImmModify.insert(m_afterImmModify.end(),
+                                      i_afterImmModify.begin(),
+                                      i_afterImmModify.end()); }
+
+///
 /// Purpose:  Get the list of callbacks afterInstall
 /// @param    -
 /// @return   The list of callbacks.
@@ -567,6 +673,16 @@ class SmfUpgradeProcedure {
         std::list < SmfCallback * >& getCbksAfterInstantiate() { return 
m_afterInstantiate; }
 
 ///
+/// Purpose:  Add the list of after instantiate callbacks
+/// @param    The list of after instantiate callbacks to add
+/// @return   none
+///
+        void  addCbksAfterInstantiate(const std::list < SmfCallback * >& 
i_afterInstantiate)
+                { m_afterInstantiate.insert(m_afterInstantiate.end(),
+                                      i_afterInstantiate.begin(),
+                                      i_afterInstantiate.end()); }
+
+///
 /// Purpose:  Get the list of callbacks afterUnlock
 /// @param    -
 /// @return   The list of callbacks.
@@ -574,6 +690,24 @@ class SmfUpgradeProcedure {
         std::list < SmfCallback * >& getCbksAfterUnlock() { return 
m_afterUnlock; }
 
 ///
+/// Purpose:  Add the list of after unlock callbacks
+/// @param    The list of after unlock callbacks to add
+/// @return   none
+///
+        void  addCbksAfterUnlock(const std::list < SmfCallback * >& 
i_afterUnlock)
+                { m_afterUnlock.insert(m_afterUnlock.end(),
+                                      i_afterUnlock.begin(),
+                                      i_afterUnlock.end()); }
+
+///
+/// Purpose:  Mark the procedure as merged or not
+/// @param    i_state a bool indicating if merged
+/// @return   -
+///
+        void setIsMergedProcedure(bool i_state)
+                { m_isMergedProcedure = i_state; }
+
+///
 /// Purpose:  Reset the object counter of upgrade procedures
 /// @param    -
 /// @return   -
@@ -630,6 +764,7 @@ class SmfUpgradeProcedure {
         std::list < SmfCallback * >m_afterInstantiate;   //Container of the 
procedure callbacks to be invoked onstep, ataction
         std::list < SmfCallback * >m_afterUnlock;   //Container of the 
procedure callbacks to be invoked onstep, ataction
        sem_t m_semaphore;
+        bool m_isMergedProcedure;
 };
 
 //////////////////////////////////////////////////
diff --git a/osaf/services/saf/smfsv/smfd/SmfUpgradeStep.cc 
b/osaf/services/saf/smfsv/smfd/SmfUpgradeStep.cc
--- a/osaf/services/saf/smfsv/smfd/SmfUpgradeStep.cc
+++ b/osaf/services/saf/smfsv/smfd/SmfUpgradeStep.cc
@@ -75,7 +75,7 @@ SmfUpgradeStep::SmfUpgradeStep():
    m_stepState(SA_SMF_STEP_INITIAL),
    m_maxRetry(0), 
    m_retryCount(0), 
-   m_restartOption(1), //True 
+   m_restartOption(1), //True
    m_procedure(NULL),
    m_stepType(NULL),
    m_switchOver(false)
@@ -93,6 +93,7 @@ SmfUpgradeStep::~SmfUpgradeStep()
        for (it = m_modificationList.begin(); it != m_modificationList.end(); 
++it) {
                delete(*it);
        }
+
         delete m_stepType;
 }
 
@@ -426,7 +427,7 @@ SmfUpgradeStep::addSwRemove(std::list<Sm
 
//------------------------------------------------------------------------------
 // getSwRemoveList()
 
//------------------------------------------------------------------------------
-const std::list < SmfBundleRef > &
+std::list < SmfBundleRef > &
 SmfUpgradeStep::getSwRemoveList()
 {
        return m_swRemoveList;
@@ -454,7 +455,7 @@ SmfUpgradeStep::addSwAdd(std::list<SmfBu
 
//------------------------------------------------------------------------------
 // getSwAddList()
 
//------------------------------------------------------------------------------
-const std::list < SmfBundleRef > &
+std::list < SmfBundleRef > &
 SmfUpgradeStep::getSwAddList()
 {
        return m_swAddList;
@@ -1609,6 +1610,30 @@ SmfUpgradeStep::calculateStepType()
 }
 
 
//------------------------------------------------------------------------------
+// calculateStepTypeForMergedSingle()
+//------------------------------------------------------------------------------
+SaAisErrorT 
+SmfUpgradeStep::calculateStepTypeForMergedSingle()
+{
+        TRACE_ENTER();
+        bool activateUsed;
+        if((smfd_cb->nodeBundleActCmd == NULL) || 
(strcmp(smfd_cb->nodeBundleActCmd,"") == 0)) {
+                activateUsed = false;
+        }
+        else {
+                activateUsed = true;
+        }
+
+        if (activateUsed == false)
+                this->setStepType(new SmfStepTypeClusterReboot(this));
+        else
+                this->setStepType(new SmfStepTypeClusterRebootAct(this));
+
+        TRACE_LEAVE();
+        return SA_AIS_OK;
+}
+
+//------------------------------------------------------------------------------
 // isCurrentNode()
 
//------------------------------------------------------------------------------
 bool 
diff --git a/osaf/services/saf/smfsv/smfd/SmfUpgradeStep.hh 
b/osaf/services/saf/smfsv/smfd/SmfUpgradeStep.hh
--- a/osaf/services/saf/smfsv/smfd/SmfUpgradeStep.hh
+++ b/osaf/services/saf/smfsv/smfd/SmfUpgradeStep.hh
@@ -234,6 +234,16 @@ class SmfUpgradeStep {
        void addActivationUnit(const unitNameAndState & i_activationUnit);
 
 ///
+/// Purpose:  Add a list of activation units
+/// @param    i_activationUnits A list of unitNameAndState
+/// @return   None
+///
+       void addActivationUnits(const std::list < unitNameAndState > & 
i_activationUnits)
+                { 
m_activationUnit.m_actedOn.insert(m_activationUnit.m_actedOn.end(),
+                                     i_activationUnits.begin(),
+                                     i_activationUnits.end()); }
+
+///
 /// Purpose:  Get the activation unit DN
 /// @param     
 /// @return   A list of DN to activation units
@@ -246,6 +256,16 @@ class SmfUpgradeStep {
 /// @return   None
 ///
        void addDeactivationUnit(const unitNameAndState & i_deactivationUnit);
+  
+///
+/// Purpose:  Add a list of deactivation units
+/// @param    i_deactivationUnits A list of unitNameAndState
+/// @return   None
+///
+       void addDeactivationUnits(const std::list < unitNameAndState > & 
i_deactivationUnits)
+                { 
m_deactivationUnit.m_actedOn.insert(m_deactivationUnit.m_actedOn.end(),
+                                     i_deactivationUnits.begin(),
+                                     i_deactivationUnits.end()); }
 
 ///
 /// Purpose:  Get the deactivation unit DN
@@ -253,6 +273,14 @@ class SmfUpgradeStep {
 /// @return   A list of DN to deactivation units
 ///
        const std::list < unitNameAndState > &getDeactivationUnitList();
+  
+///
+/// Purpose:  Clean the deactivation unit list
+/// @param    None
+/// @return   None
+///
+       void cleanDeactivationUnitList(void)
+                { m_deactivationUnit.m_actedOn.clear(); }
 
 ///
 /// Purpose:  Add a sw bundle to remove
@@ -261,13 +289,15 @@ class SmfUpgradeStep {
 ///
        void addSwRemove(const std::list < SmfBundleRef * >&i_swRemove);
        void addSwRemove(std::list<SmfBundleRef> const& i_swRemove);
+       void addSwRemove(SmfBundleRef& i_swRemove)
+                { m_swRemoveList.push_back(i_swRemove); }
 
 ///
 /// Purpose:  Get the sw remove list
 /// @param     
 /// @return   A list of bundles to remove
 ///
-       const std::list < SmfBundleRef > &getSwRemoveList();
+       std::list < SmfBundleRef > &getSwRemoveList();
 
 ///
 /// Purpose:  Add a sw bundle to add
@@ -276,13 +306,14 @@ class SmfUpgradeStep {
 ///
        void addSwAdd(const std::list < SmfBundleRef* >&i_swAdd);
        void addSwAdd(std::list<SmfBundleRef> const& i_swAdd);
-
+       void addSwAdd(SmfBundleRef& i_swAdd)
+                { m_swAddList.push_back(i_swAdd); }
 ///
 /// Purpose:  Get the sw add list
 /// @param     
 /// @return   A list of bundles to add
 ///
-       const std::list < SmfBundleRef > &getSwAddList();
+       std::list < SmfBundleRef > &getSwAddList();
 
 ///
 /// Purpose:  Add a modification
@@ -292,6 +323,16 @@ class SmfUpgradeStep {
        void addModification(SmfImmModifyOperation * i_modification);
 
 ///
+/// Purpose:  Add a list of modifications
+/// @param    i_modifications A list of Imm modifications
+/// @return   None
+///
+       void addModifications(std::list < SmfImmOperation * >& i_modifications)
+                { m_modificationList.insert(m_modificationList.end(),
+                                     i_modifications.begin(),
+                                     i_modifications.end()); }
+
+///
 /// Purpose:  Get modifications
 /// @param    None
 /// @return   A list of pointers to SmfImmOperation objects
@@ -569,12 +610,19 @@ class SmfUpgradeStep {
 
 ///
 /// Purpose:  calculateStepType  
-/// @param    i_needsReboot true if reboot is needed 
+/// @param    none
 /// @return   SA_AIS_OK if calculation went OK 
 ///
        SaAisErrorT calculateStepType();
 
 ///
+/// Purpose:  calculateStepTypeForMergedSingle
+/// @param    none
+/// @return   SA_AIS_OK if calculation went OK
+///
+       SaAisErrorT calculateStepTypeForMergedSingle();
+
+  ///
 /// Purpose:  isCurrentNode  
 /// @param    - 
 /// @return   true if the calling component executes on the given AMF node, 
otherwise false.
diff --git a/osaf/services/saf/smfsv/smfd/SmfUtils.cc 
b/osaf/services/saf/smfsv/smfd/SmfUtils.cc
--- a/osaf/services/saf/smfsv/smfd/SmfUtils.cc
+++ b/osaf/services/saf/smfsv/smfd/SmfUtils.cc
@@ -1272,3 +1272,18 @@ smfStateToString(const uint32_t& i_state
                return "Unknown state ID";
        }
 }
+
+bool compare_du_part (unitNameAndState& first, unitNameAndState& second)
+{
+  unsigned int i=0;
+  while ( (i<first.name.length()) && (i<second.name.length()) )
+  {
+    if (tolower(first.name[i])<tolower(second.name[i])) return true;
+    else if (tolower(first.name[i])>tolower(second.name[i])) return false;
+    ++i;
+  }
+  return ( first.name.length() < second.name.length() );
+}
+
+bool unique_du_part (unitNameAndState& first, unitNameAndState& second)
+{ return ( first.name == second.name ); }
diff --git a/osaf/services/saf/smfsv/smfd/SmfUtils.hh 
b/osaf/services/saf/smfsv/smfd/SmfUtils.hh
--- a/osaf/services/saf/smfsv/smfd/SmfUtils.hh
+++ b/osaf/services/saf/smfsv/smfd/SmfUtils.hh
@@ -31,6 +31,7 @@
 
 #include "smfd.h"
 #include "smfd_smfnd.h"
+#include "SmfUpgradeStep.hh"
 
 /* ========================================================================
  *   DEFINITIONS
@@ -65,6 +66,8 @@ extern "C" {
         extern int  smf_system(std::string i_cmd);
        extern void updateSaflog(const std::string& i_dn, const uint32_t& 
i_stateId, const uint32_t& i_newState, const uint32_t& i_oldState);
        extern const std::string smfStateToString(const uint32_t& i_stateId, 
const uint32_t& i_state);
+        extern bool compare_du_part (unitNameAndState& first, 
unitNameAndState& second);
+        extern bool unique_du_part (unitNameAndState& first, unitNameAndState& 
second);
 
 #ifdef __cplusplus
 }
diff --git a/osaf/services/saf/smfsv/smfd/smfd.h 
b/osaf/services/saf/smfsv/smfd/smfd.h
--- a/osaf/services/saf/smfsv/smfd/smfd.h
+++ b/osaf/services/saf/smfsv/smfd/smfd.h
@@ -55,6 +55,12 @@ extern "C" {
 #define SMF_NODE_ID_CONTROLLER_2 0x2020f
 #define SMF_CAMPAIGN_OI_NAME "safSmfCampaign"
 #define SMF_PROC_OI_NAME_PREFIX "safSmfProc"
+#define SMF_MERGED_SS_PROC_NAME "safSmfProc=SmfSSMergedProc"
+
+/* SMF execution modes */
+#define SMF_STANDARD_MODE 0
+#define SMF_MERGE_TO_SINGLE_STEP 1
+#define SMF_MERGE_TO_NODE_ROLLING 2
 
 /* ========================================================================
  *   TYPE DEFINITIONS
diff --git a/osaf/services/saf/smfsv/smfd/smfd_campaign_oi.cc 
b/osaf/services/saf/smfsv/smfd/smfd_campaign_oi.cc
--- a/osaf/services/saf/smfsv/smfd/smfd_campaign_oi.cc
+++ b/osaf/services/saf/smfsv/smfd/smfd_campaign_oi.cc
@@ -48,6 +48,7 @@ static const SaImmOiImplementerNameT imp
 static const SaImmClassNameT campaignClassName = (SaImmClassNameT) 
"SaSmfCampaign";
 static const SaImmClassNameT smfConfigClassName = (SaImmClassNameT) 
"OpenSafSmfConfig";
 static const SaImmClassNameT smfSwBundleClassName = (SaImmClassNameT) 
"SaSmfSwBundle";
+static const SaImmClassNameT openSafSmfExecControlClassName = 
(SaImmClassNameT) "OpenSafSmfExecControl";
 
 typedef enum {
         SMF_CLASS_UNKNOWN  = 0,
@@ -228,6 +229,9 @@ static SaAisErrorT saImmOiCcbCompletedCa
                                 rc = SA_AIS_ERR_BAD_OPERATION;
                                 goto done;
 
+                        } else if 
(strcmp(ccbUtilOperationData->param.create.className, 
openSafSmfExecControlClassName) == 0) {
+                                ccbUtilOperationData->userData = 
(void*)SMF_CLASS_CONFIG;
+                                TRACE("Create %s", OPENSAF_SMF_EXEC_CONTROL); 
// Creation always allowed
                         //Handle unknown
                         } else {
                                 //Save the class name enum for use in later 
phases
@@ -329,6 +333,9 @@ static SaAisErrorT saImmOiCcbCompletedCa
 
                                 goto done;
                                 //Handle any unknown object
+                        } else if (className == 
openSafSmfExecControlClassName) {
+                                TRACE("Delete campaign %s", 
objToDelete.c_str()); // Delete always allowed
+                                ccbUtilOperationData->userData = 
(void*)SMF_CLASS_CONFIG;
                         } else {
                                 LOG_NO("Unknown object %s, can't be deleted", 
objToDelete.c_str());
                                 //Save the class name enum for use in later 
phases
@@ -498,7 +505,9 @@ static SaAisErrorT saImmOiCcbCompletedCa
                                 TRACE("Modification of object %s", 
objToModify.c_str());
                                 //Save the class name enum for use in later 
phases
                                 ccbUtilOperationData->userData = 
(void*)SMF_CLASS_BUNDLE;
-
+                        } else if (className == 
openSafSmfExecControlClassName) {
+                                TRACE("Modification of object %s", 
objToModify.c_str()); // Always allow modification
+                                ccbUtilOperationData->userData = 
(void*)SMF_CLASS_CONFIG;
                         //Handle any unknown object
                         } else {
                                 LOG_NO("Unknown object %s, can't be modified" 
,objToModify.c_str());
@@ -714,7 +723,6 @@ uint32_t create_campaign_objects(smfd_cb
        TRACE("Check if any executing campaign");
 
        if (execCampaign != NULL) {
-               /* Start executing the campaign */
                LOG_NO("Continue executing ongoing campaign %s", 
execCampaign->getDn().c_str());
 
                if (SmfCampaignThread::start(execCampaign) == 0) {
@@ -726,7 +734,6 @@ uint32_t create_campaign_objects(smfd_cb
                        LOG_NO("create_campaign_objects, failed to start 
campaign");
                }
        }
-
        TRACE_LEAVE();
        return NCSCC_RC_SUCCESS;
 }
@@ -789,6 +796,13 @@ uint32_t campaign_oi_activate(smfd_cb_t 
                return NCSCC_RC_FAILURE;
        }
 
+        rc = immutil_saImmOiClassImplementerSet(cb->campaignOiHandle, 
openSafSmfExecControlClassName);
+        if (rc != SA_AIS_OK) {
+                TRACE("immutil_saImmOiClassImplementerSet smfConfigOiHandle 
failed rc=%u class name=%s",
+                               rc, (char*)openSafSmfExecControlClassName);
+                return NCSCC_RC_FAILURE;
+        }
+
        /* Create all Campaign objects found in the IMM  */
        if (create_campaign_objects(cb) != NCSCC_RC_SUCCESS) {
                return NCSCC_RC_FAILURE;
@@ -867,6 +881,32 @@ uint32_t campaign_oi_init(smfd_cb_t * cb
        return NCSCC_RC_SUCCESS;
 }
 
+SaUint32T readExecControlObject(const char* openSafSmfExecControlDN)
+{
+       SmfImmUtils immUtil;
+       SaImmAttrValuesT_2 **attributes;
+       if (openSafSmfExecControlDN == NULL || strcmp(openSafSmfExecControlDN, 
"") == 0) {
+               LOG_NO("%s is not set, using standard mode", 
OPENSAF_SMF_EXEC_CONTROL);
+               openSafSmfExecControlDN = NULL;
+               return SMF_STANDARD_MODE;
+       }
+       else {
+               LOG_NO("%s is set to %s", OPENSAF_SMF_EXEC_CONTROL, 
openSafSmfExecControlDN);
+       }
+       if (immUtil.getObject(openSafSmfExecControlDN, &attributes) == false) {
+               LOG_NO("Failed to get object from attribute %s, using standard 
mode", OPENSAF_SMF_EXEC_CONTROL);
+               return SMF_STANDARD_MODE;
+       }
+       const SaUint32T* mode = immutil_getUint32Attr((const SaImmAttrValuesT_2 
**)attributes,
+               "procExecMode", 0);
+       if (mode == NULL) {
+               LOG_WA("Attribute value was NULL for procExecMode, using 
standard mode");
+               return SMF_STANDARD_MODE;
+       }
+       LOG_NO("procExecMode is set to %u", *mode);
+       return *mode;
+}
+
 /**
  * read SMF configuration object and set control block data accordingly.
  * @param cb
@@ -1107,6 +1147,11 @@ uint32_t read_config_and_set_control_blo
                LOG_NO("smfKeepDuState = %d", *keepDuState);
        }
 
+       const char* smfExecControlDN = immutil_getStringAttr((const 
SaImmAttrValuesT_2 **)attributes,
+                                                            
OPENSAF_SMF_EXEC_CONTROL, 0);
+
+       SaUint32T procExecMode = readExecControlObject(smfExecControlDN);
+
        cb->backupCreateCmd = strdup(backupCreateCmd);
        cb->bundleCheckCmd = strdup(bundleCheckCmd);
        cb->nodeCheckCmd = strdup(nodeCheckCmd);
@@ -1125,6 +1170,7 @@ uint32_t read_config_and_set_control_blo
        cb->smfVerifyEnable = *smfVerifyEnable;
        cb->smfVerifyTimeout = *verifyTimeout;
        cb->smfKeepDuState = *keepDuState;
+       cb->procExecutionMode = procExecMode;
 
        TRACE_LEAVE();
        return NCSCC_RC_SUCCESS;
@@ -1178,6 +1224,12 @@ void* smfd_coi_reinit_thread(void * _cb)
                        LOG_ER("immutil_saImmOiClassImplementerSet 
smfConfigOiHandle failed rc=%u class name=%s", rc, (char*)smfSwBundleClassName);
                        exit(EXIT_FAILURE);
                }
+
+               rc = immutil_saImmOiClassImplementerSet(cb->campaignOiHandle, 
openSafSmfExecControlClassName);
+               if (rc != SA_AIS_OK) {
+                       LOG_ER("immutil_saImmOiClassImplementerSet 
smfConfigOiHandle failed rc=%u class name=%s", rc, 
(char*)openSafSmfExecControlClassName);
+                       exit(EXIT_FAILURE);
+               }
        }
 
        TRACE_LEAVE();
@@ -1201,3 +1253,4 @@ void smfd_coi_reinit_bg(smfd_cb_t *cb)
        
        TRACE_LEAVE();
 }
+
diff --git a/osaf/services/saf/smfsv/smfd/smfd_cb.h 
b/osaf/services/saf/smfsv/smfd/smfd_cb.h
--- a/osaf/services/saf/smfsv/smfd/smfd_cb.h
+++ b/osaf/services/saf/smfsv/smfd/smfd_cb.h
@@ -66,6 +66,12 @@ typedef struct smfd_cb {
        uint32_t no_of_smfnd;
        pthread_mutex_t lock;                     /* Used by smfd_cb_t 
lock/unlock functions */
        uint32_t maxDnLength;                     /* Max DN length */
+        uint32_t procExecutionMode;               /* Control the procedure 
execution modes
+                                                     SMF_STANDARD 0
+                                                     SMF_MERGE_TO_SINGLE_STEP 1
+                                                     SMF_MERGE_TO_NODE_ROLLING 
2
+                                                   */
+
 } smfd_cb_t;
 
 #ifdef __cplusplus

------------------------------------------------------------------------------
Monitor Your Dynamic Infrastructure at Any Scale With Datadog!
Get real-time metrics from all of your servers, apps and tools
in one place.
SourceForge users - Click here to start your Free Trial of Datadog now!
http://pubads.g.doubleclick.net/gampad/clk?id=241902991&iu=/4140
_______________________________________________
Opensaf-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to