ACK, with a few comments.

tested in osaftest.


On 09/23/2015 12:29 PM, Ingvar Bergstrom wrote:
>   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) {
[rafael] Looks like it would never get here because of the above if 
statement/
> +                       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;
> +        }
> +
[rafael] Why is the NO_OP ignored with the merged procedures? Should 
this not be inside an "if (getProcExecutionMode() == MERGED_PROC)" ?
>       //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


------------------------------------------------------------------------------
_______________________________________________
Opensaf-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to