osaf/services/saf/smfsv/config/smfsv_classes.xml    |  1084 +++++++++---------
 osaf/services/saf/smfsv/smfd/Makefile.am            |     8 +-
 osaf/services/saf/smfsv/smfd/SmfCampState.cc        |   151 +--
 osaf/services/saf/smfsv/smfd/SmfCampaign.cc         |    77 +-
 osaf/services/saf/smfsv/smfd/SmfCampaign.hh         |     1 +
 osaf/services/saf/smfsv/smfd/SmfExecControl.cc      |   363 ++++++
 osaf/services/saf/smfsv/smfd/SmfExecControl.h       |    59 +
 osaf/services/saf/smfsv/smfd/SmfExecControlHdl.cc   |   506 ++++++++
 osaf/services/saf/smfsv/smfd/SmfExecControlHdl.h    |   126 ++
 osaf/services/saf/smfsv/smfd/SmfProcState.cc        |    28 +-
 osaf/services/saf/smfsv/smfd/SmfUpgradeCampaign.cc  |    39 +-
 osaf/services/saf/smfsv/smfd/SmfUpgradeCampaign.hh  |    35 +-
 osaf/services/saf/smfsv/smfd/SmfUpgradeProcedure.cc |    27 +-
 osaf/services/saf/smfsv/smfd/SmfUpgradeProcedure.hh |    18 +-
 osaf/services/saf/smfsv/smfd/SmfUpgradeStep.cc      |    49 +
 osaf/services/saf/smfsv/smfd/SmfUpgradeStep.hh      |    13 +-
 osaf/services/saf/smfsv/smfd/smfd.h                 |     2 +-
 osaf/services/saf/smfsv/smfd/smfd_campaign_oi.cc    |    32 -
 osaf/services/saf/smfsv/smfd/smfd_cb.h              |     5 -
 19 files changed, 1842 insertions(+), 781 deletions(-)


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
@@ -1,535 +1,555 @@
 <?xml version="1.0" encoding="utf-8"?>
 <imm:IMM-contents xmlns:imm="http://www.saforum.org/IMMSchema"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:noNamespaceSchemaLocation="SAI-AIS-IMM-XSD-A.02.13.xsd">
-       <class name="SaSmfCampaign">
-               <category>SA_CONFIG</category>
-               <rdn>
-                       <name>safSmfCampaign</name>
-                       <type>SA_STRING_T</type>
-                       <category>SA_CONFIG</category>
-                       <flag>SA_INITIALIZED</flag>
-               </rdn>
-               <attr>
-                       <name>saSmfCmpgFileUri</name>
-                       <type>SA_STRING_T</type>
-                       <category>SA_CONFIG</category>
-                       <flag>SA_WRITABLE</flag>
-               </attr>
-               <attr>
-                       <name>saSmfCmpgConfigBase</name>
-                       <type>SA_TIME_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-               </attr>
-               <attr>
-                       <name>saSmfCmpgExpectedTime</name>
-                       <type>SA_TIME_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-               </attr>
-               <attr>
-                       <name>saSmfCmpgElapsedTime</name>
-                       <type>SA_TIME_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-               </attr>
-               <attr>
-                       <name>saSmfCmpgState</name>
-                       <type>SA_UINT32_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-                       <default-value>1</default-value>
-               </attr>
-               <attr>
-                       <name>saSmfCmpgError</name>
-                       <type>SA_STRING_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-                       <flag>SA_MULTI_VALUE</flag>
-               </attr>
-       </class>
-       <class name="SaSmfProcedure">
-               <category>SA_RUNTIME</category>
-               <rdn>
-                       <name>safSmfProcedure</name>
-                       <type>SA_STRING_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-               </rdn>
-               <attr>
-                       <name>saSmfProcExecLevel</name>
-                       <type>SA_UINT32_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-               </attr>
-               <attr>
-                       <name>saSmfProcMustKeepSIs</name>
-                       <type>SA_NAME_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-                       <flag>SA_MULTI_VALUE</flag>
-               </attr>
-               <attr>
-                       <name>saSmfProcAcceptSIOutage</name>
-                       <type>SA_NAME_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-                       <flag>SA_MULTI_VALUE</flag>
-               </attr>
-               <attr>
-                       <name>saSmfProcMaxNumSIsOutage</name>
-                       <type>SA_UINT32_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-               </attr>
-               <attr>
-                       <name>saSmfProcUpgrMethod</name>
-                       <type>SA_UINT32_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-               </attr>
-               <attr>
-                       <name>saSmfProcDisableSimultanExec</name>
-                       <type>SA_UINT32_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-               </attr>
-               <attr>
-                       <name>saSmfProcPeriod</name>
-                       <type>SA_TIME_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-               </attr>
-               <attr>
-                       <name>saSmfProcState</name>
-                       <type>SA_UINT32_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-               </attr>
-               <attr>
-                       <name>saSmfProcError</name>
-                       <type>SA_STRING_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-                       <flag>SA_MULTI_VALUE</flag>
-               </attr>
-       </class>
-       <class name="SaSmfStep">
-               <category>SA_RUNTIME</category>
-               <rdn>
-                       <name>safSmfStep</name>
-                       <type>SA_STRING_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-               </rdn>
-               <attr>
-                       <name>saSmfStepMaxRetry</name>
-                       <type>SA_UINT32_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-               </attr>
-               <attr>
-                       <name>saSmfStepRetryCount</name>
-                       <type>SA_UINT32_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-               </attr>
-               <attr>
-                       <name>saSmfStepRestartOption</name>
-                       <type>SA_UINT32_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-               </attr>
-               <attr>
-                       <name>saSmfStepState</name>
-                       <type>SA_UINT32_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-               </attr>
-               <attr>
-                       <name>saSmfStepError</name>
-                       <type>SA_STRING_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-                       <flag>SA_MULTI_VALUE</flag>
-               </attr>
-       </class>
-       <class name="SaSmfDeactivationUnit">
-               <category>SA_RUNTIME</category>
-               <rdn>
-                       <name>safSmfDu</name>
-                       <type>SA_STRING_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-               </rdn>
-               <attr>
-                       <name>saSmfDuActedOn</name>
-                       <type>SA_NAME_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-                       <flag>SA_MULTI_VALUE</flag>
-               </attr>
-               <attr>
-                       <name>saSmfDuEntityToRemove</name>
-                       <type>SA_NAME_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-                       <flag>SA_MULTI_VALUE</flag>
-               </attr>
-       </class>
-       <class name="SaSmfActivationUnit">
-               <category>SA_RUNTIME</category>
-               <rdn>
-                       <name>safSmfAu</name>
-                       <type>SA_STRING_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-               </rdn>
-               <attr>
-                       <name>saSmfAuActedOn</name>
-                       <type>SA_NAME_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-                       <flag>SA_MULTI_VALUE</flag>
-               </attr>
-               <attr>
-                       <name>saSmfAuEntityToAdd</name>
-                       <type>SA_NAME_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-                       <flag>SA_MULTI_VALUE</flag>
-               </attr>
-       </class>
-       <class name="SaSmfImageNodes">
-               <category>SA_RUNTIME</category>
-               <rdn>
-                       <name>safImageNode</name>
-                       <type>SA_STRING_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-               </rdn>
-               <attr>
-                       <name>saSmfINSwBundle</name>
-                       <type>SA_NAME_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-               </attr>
-               <attr>
-                       <name>saSmfINNode</name>
-                       <type>SA_NAME_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-                       <flag>SA_MULTI_VALUE</flag>
-               </attr>
-       </class>
-       <class name="OpenSafSmfConfig">
-               <category>SA_CONFIG</category>
-               <rdn>
-                       <name>smfConfig</name>
-                       <type>SA_STRING_T</type>
-                       <category>SA_CONFIG</category>
-                       <flag>SA_INITIALIZED</flag>
-               </rdn>
-               <attr>
-                       <name>smfBackupCreateCmd</name>
-                       <type>SA_STRING_T</type>
-                       <category>SA_CONFIG</category>
-                       <flag>SA_INITIALIZED</flag>
-                       <flag>SA_WRITABLE</flag>
-               </attr>
-               <attr>
-                       <name>smfBundleCheckCmd</name>
-                       <type>SA_STRING_T</type>
-                       <category>SA_CONFIG</category>
-                       <flag>SA_INITIALIZED</flag>
-                       <flag>SA_WRITABLE</flag>
-               </attr>
-               <attr>
-                       <name>smfNodeCheckCmd</name>
-                       <type>SA_STRING_T</type>
-                       <category>SA_CONFIG</category>
-                       <flag>SA_INITIALIZED</flag>
-                       <flag>SA_WRITABLE</flag>
-               </attr>
-               <attr>
-                       <name>smfRepositoryCheckCmd</name>
-                       <type>SA_STRING_T</type>
-                       <category>SA_CONFIG</category>
-                       <flag>SA_INITIALIZED</flag>
-                       <flag>SA_WRITABLE</flag>
-               </attr>
-               <attr>
-                       <name>smfClusterRebootCmd</name>
-                       <type>SA_STRING_T</type>
-                       <category>SA_CONFIG</category>
-                       <flag>SA_INITIALIZED</flag>
-                       <flag>SA_WRITABLE</flag>
-               </attr>
-               <attr>
-                       <name>smfAdminOpTimeout</name>
-                       <type>SA_TIME_T</type>
-                       <category>SA_CONFIG</category>
-                       <flag>SA_INITIALIZED</flag>
-                       <flag>SA_WRITABLE</flag>
-               </attr>
-               <attr>
-                       <name>smfCliTimeout</name>
-                       <type>SA_TIME_T</type>
-                       <category>SA_CONFIG</category>
-                       <flag>SA_INITIALIZED</flag>
-                       <flag>SA_WRITABLE</flag>
-               </attr>
-               <attr>
-                       <name>smfRebootTimeout</name>
-                       <type>SA_TIME_T</type>
-                       <category>SA_CONFIG</category>
-                       <flag>SA_INITIALIZED</flag>
-                       <flag>SA_WRITABLE</flag>
-               </attr>
-               <attr>
-                       <name>smfNodeBundleActCmd</name>
-                       <type>SA_STRING_T</type>
-                       <category>SA_CONFIG</category>
-                       <flag>SA_WRITABLE</flag>
-               </attr>
-               <attr>
-                       <name>smfSiSwapSiName</name>
-                       <type>SA_STRING_T</type>
-                       <category>SA_CONFIG</category>
-                       <flag>SA_WRITABLE</flag>
-               </attr>
-               <attr>
-                       <name>smfSiSwapMaxRetry</name>
-                       <type>SA_UINT32_T</type>
-                       <category>SA_CONFIG</category>
-                       <flag>SA_WRITABLE</flag>
-               </attr>
-               <attr>
-                       <name>smfCampMaxRestart</name>
-                       <type>SA_UINT32_T</type>
-                       <category>SA_CONFIG</category>
-                       <flag>SA_WRITABLE</flag>
-               </attr>
-               <attr>
-                       <name>smfImmPersistCmd</name>
-                       <type>SA_STRING_T</type>
-                       <category>SA_CONFIG</category>
-                       <flag>SA_WRITABLE</flag>
-               </attr>
-               <attr>
-                       <name>smfNodeRebootCmd</name>
-                       <type>SA_STRING_T</type>
-                       <category>SA_CONFIG</category>
-                       <flag>SA_WRITABLE</flag>
-               </attr>
-               <attr>
-                       <name>smfInactivatePbeDuringUpgrade</name>
-                       <type>SA_UINT32_T</type>
-                       <category>SA_CONFIG</category>
-                       <flag>SA_WRITABLE</flag>
-               </attr>
-                <attr>
-                        <name>smfVerifyEnable</name>
-                        <type>SA_UINT32_T</type>
-                        <category>SA_CONFIG</category>
-                        <flag>SA_WRITABLE</flag>
-                        <default-value>0</default-value>
-                </attr>
-                <attr>
-                        <name>smfVerifyTimeout</name>
-                        <type>SA_TIME_T</type>
-                        <category>SA_CONFIG</category>
-                        <flag>SA_WRITABLE</flag>
-                        <default-value>100000000000</default-value>
-                </attr>
-               <attr>
-                       <name>smfClusterControllers</name>
-                       <type>SA_STRING_T</type>
-                       <category>SA_CONFIG</category>
-                        <flag>SA_WRITABLE</flag>
-                       <flag>SA_MULTI_VALUE</flag>
-               </attr>
-               <attr>
-                       <name>smfSSAffectedNodesEnable</name>
-                       <type>SA_UINT32_T</type>
-                       <category>SA_CONFIG</category>
-                        <flag>SA_WRITABLE</flag>
-                        <default-value>0</default-value>
-               </attr>
-               <attr>
-                       <name>smfKeepDuState</name>
-                       <type>SA_UINT32_T</type>
-                       <category>SA_CONFIG</category>
-                        <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>
-               <rdn>
-                       <name>smfRestartInfo</name>
-                       <type>SA_STRING_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-               </rdn>
-               <attr>
-                       <name>smfCampRestartCnt</name>
-                       <type>SA_UINT32_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-               </attr>
-       </class>
-       <class name="OpenSafSmfSingleStepInfo">
-               <category>SA_RUNTIME</category>
-               <rdn>
-                       <name>smfSingleStepInfo</name>
-                       <type>SA_STRING_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-               </rdn>
-               <attr>
-                       <name>smfRebootType</name>
-                       <type>SA_UINT32_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-               </attr>
-       </class>
-       <class name="OpenSafSmfCampRestartIndicator">
-               <category>SA_RUNTIME</category>
-               <rdn>
-                       <name>smfCampaignRestartIndicator</name>
-                       <type>SA_STRING_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-               </rdn>
-       </class>
-       <class name="OpenSafSmfPbeIndicator">
-               <category>SA_RUNTIME</category>
-               <rdn>
-                       <name>safRdn</name>
-                       <type>SA_STRING_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-               </rdn>
-       </class>
-       <class name="OpenSafSmfRollbackElement">
-               <category>SA_RUNTIME</category>
-               <rdn>
-                       <name>smfRollbackElement</name>
-                       <type>SA_STRING_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-               </rdn>
-       </class>
-       <class name="OpenSafSmfRollbackData">
-               <category>SA_RUNTIME</category>
-               <rdn>
-                       <name>smfRollbackData</name>
-                       <type>SA_STRING_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-               </rdn>
-               <attr>
-                       <name>smfRollbackType</name>
-                       <type>SA_STRING_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-               </attr>
-               <attr>
-                       <name>smfRollbackDn</name>
-                       <type>SA_NAME_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-               </attr>
-               <attr>
-                       <name>smfRollbackClass</name>
-                       <type>SA_STRING_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-               </attr>
-               <attr>
-                       <name>smfRollbackAttrValue</name>
-                       <type>SA_STRING_T</type>
-                       <category>SA_RUNTIME</category>
-                       <flag>SA_PERSISTENT</flag>
-                       <flag>SA_CACHED</flag>
-                       <flag>SA_MULTI_VALUE</flag>
-               </attr>
-       </class>
-       <class name="OpenSafSmfMisc">
-               <category>SA_CONFIG</category>
-               <rdn>
-                       <name>openSafSmfMisc</name>
-                       <type>SA_STRING_T</type>
-                       <category>SA_CONFIG</category>
-                       <flag>SA_INITIALIZED</flag>
-               </rdn>
-               <attr>
-                       <name>reason</name>
-                       <type>SA_STRING_T</type>
-                       <category>SA_CONFIG</category>
-                       <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>
+    <class name="SaSmfCampaign">
+        <category>SA_CONFIG</category>
+        <rdn>
+            <name>safSmfCampaign</name>
+            <type>SA_STRING_T</type>
+            <category>SA_CONFIG</category>
+            <flag>SA_INITIALIZED</flag>
+        </rdn>
+        <attr>
+            <name>saSmfCmpgFileUri</name>
+            <type>SA_STRING_T</type>
+            <category>SA_CONFIG</category>
+            <flag>SA_WRITABLE</flag>
+        </attr>
+        <attr>
+            <name>saSmfCmpgConfigBase</name>
+            <type>SA_TIME_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+        </attr>
+        <attr>
+            <name>saSmfCmpgExpectedTime</name>
+            <type>SA_TIME_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+        </attr>
+        <attr>
+            <name>saSmfCmpgElapsedTime</name>
+            <type>SA_TIME_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+        </attr>
+        <attr>
+            <name>saSmfCmpgState</name>
+            <type>SA_UINT32_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+            <default-value>1</default-value>
+        </attr>
+        <attr>
+            <name>saSmfCmpgError</name>
+            <type>SA_STRING_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+            <flag>SA_MULTI_VALUE</flag>
+        </attr>
+    </class>
+    <class name="SaSmfProcedure">
+        <category>SA_RUNTIME</category>
+        <rdn>
+            <name>safSmfProcedure</name>
+            <type>SA_STRING_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+        </rdn>
+        <attr>
+            <name>saSmfProcExecLevel</name>
+            <type>SA_UINT32_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+        </attr>
+        <attr>
+            <name>saSmfProcMustKeepSIs</name>
+            <type>SA_NAME_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+            <flag>SA_MULTI_VALUE</flag>
+        </attr>
+        <attr>
+            <name>saSmfProcAcceptSIOutage</name>
+            <type>SA_NAME_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+            <flag>SA_MULTI_VALUE</flag>
+        </attr>
+        <attr>
+            <name>saSmfProcMaxNumSIsOutage</name>
+            <type>SA_UINT32_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+        </attr>
+        <attr>
+            <name>saSmfProcUpgrMethod</name>
+            <type>SA_UINT32_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+        </attr>
+        <attr>
+            <name>saSmfProcDisableSimultanExec</name>
+            <type>SA_UINT32_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+        </attr>
+        <attr>
+            <name>saSmfProcPeriod</name>
+            <type>SA_TIME_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+        </attr>
+        <attr>
+            <name>saSmfProcState</name>
+            <type>SA_UINT32_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+        </attr>
+        <attr>
+            <name>saSmfProcError</name>
+            <type>SA_STRING_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+            <flag>SA_MULTI_VALUE</flag>
+        </attr>
+    </class>
+    <class name="SaSmfStep">
+        <category>SA_RUNTIME</category>
+        <rdn>
+            <name>safSmfStep</name>
+            <type>SA_STRING_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+        </rdn>
+        <attr>
+            <name>saSmfStepMaxRetry</name>
+            <type>SA_UINT32_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+        </attr>
+        <attr>
+            <name>saSmfStepRetryCount</name>
+            <type>SA_UINT32_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+        </attr>
+        <attr>
+            <name>saSmfStepRestartOption</name>
+            <type>SA_UINT32_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+        </attr>
+        <attr>
+            <name>saSmfStepState</name>
+            <type>SA_UINT32_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+        </attr>
+        <attr>
+            <name>saSmfStepError</name>
+            <type>SA_STRING_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+            <flag>SA_MULTI_VALUE</flag>
+        </attr>
+    </class>
+    <class name="SaSmfDeactivationUnit">
+        <category>SA_RUNTIME</category>
+        <rdn>
+            <name>safSmfDu</name>
+            <type>SA_STRING_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+        </rdn>
+        <attr>
+            <name>saSmfDuActedOn</name>
+            <type>SA_NAME_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+            <flag>SA_MULTI_VALUE</flag>
+        </attr>
+        <attr>
+            <name>saSmfDuEntityToRemove</name>
+            <type>SA_NAME_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+            <flag>SA_MULTI_VALUE</flag>
+        </attr>
+    </class>
+    <class name="SaSmfActivationUnit">
+        <category>SA_RUNTIME</category>
+        <rdn>
+            <name>safSmfAu</name>
+            <type>SA_STRING_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+        </rdn>
+        <attr>
+            <name>saSmfAuActedOn</name>
+            <type>SA_NAME_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+            <flag>SA_MULTI_VALUE</flag>
+        </attr>
+        <attr>
+            <name>saSmfAuEntityToAdd</name>
+            <type>SA_NAME_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+            <flag>SA_MULTI_VALUE</flag>
+        </attr>
+    </class>
+    <class name="SaSmfImageNodes">
+        <category>SA_RUNTIME</category>
+        <rdn>
+            <name>safImageNode</name>
+            <type>SA_STRING_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+        </rdn>
+        <attr>
+            <name>saSmfINSwBundle</name>
+            <type>SA_NAME_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+        </attr>
+        <attr>
+            <name>saSmfINNode</name>
+            <type>SA_NAME_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+            <flag>SA_MULTI_VALUE</flag>
+        </attr>
+    </class>
+    <class name="OpenSafSmfConfig">
+        <category>SA_CONFIG</category>
+        <rdn>
+            <name>smfConfig</name>
+            <type>SA_STRING_T</type>
+            <category>SA_CONFIG</category>
+            <flag>SA_INITIALIZED</flag>
+        </rdn>
+        <attr>
+            <name>smfBackupCreateCmd</name>
+            <type>SA_STRING_T</type>
+            <category>SA_CONFIG</category>
+            <flag>SA_INITIALIZED</flag>
+            <flag>SA_WRITABLE</flag>
+        </attr>
+        <attr>
+            <name>smfBundleCheckCmd</name>
+            <type>SA_STRING_T</type>
+            <category>SA_CONFIG</category>
+            <flag>SA_INITIALIZED</flag>
+            <flag>SA_WRITABLE</flag>
+        </attr>
+        <attr>
+            <name>smfNodeCheckCmd</name>
+            <type>SA_STRING_T</type>
+            <category>SA_CONFIG</category>
+            <flag>SA_INITIALIZED</flag>
+            <flag>SA_WRITABLE</flag>
+        </attr>
+        <attr>
+            <name>smfRepositoryCheckCmd</name>
+            <type>SA_STRING_T</type>
+            <category>SA_CONFIG</category>
+            <flag>SA_INITIALIZED</flag>
+            <flag>SA_WRITABLE</flag>
+        </attr>
+        <attr>
+            <name>smfClusterRebootCmd</name>
+            <type>SA_STRING_T</type>
+            <category>SA_CONFIG</category>
+            <flag>SA_INITIALIZED</flag>
+            <flag>SA_WRITABLE</flag>
+        </attr>
+        <attr>
+            <name>smfAdminOpTimeout</name>
+            <type>SA_TIME_T</type>
+            <category>SA_CONFIG</category>
+            <flag>SA_INITIALIZED</flag>
+            <flag>SA_WRITABLE</flag>
+        </attr>
+        <attr>
+            <name>smfCliTimeout</name>
+            <type>SA_TIME_T</type>
+            <category>SA_CONFIG</category>
+            <flag>SA_INITIALIZED</flag>
+            <flag>SA_WRITABLE</flag>
+        </attr>
+        <attr>
+            <name>smfRebootTimeout</name>
+            <type>SA_TIME_T</type>
+            <category>SA_CONFIG</category>
+            <flag>SA_INITIALIZED</flag>
+            <flag>SA_WRITABLE</flag>
+        </attr>
+        <attr>
+            <name>smfNodeBundleActCmd</name>
+            <type>SA_STRING_T</type>
+            <category>SA_CONFIG</category>
+            <flag>SA_WRITABLE</flag>
+        </attr>
+        <attr>
+            <name>smfSiSwapSiName</name>
+            <type>SA_STRING_T</type>
+            <category>SA_CONFIG</category>
+            <flag>SA_WRITABLE</flag>
+        </attr>
+        <attr>
+            <name>smfSiSwapMaxRetry</name>
+            <type>SA_UINT32_T</type>
+            <category>SA_CONFIG</category>
+            <flag>SA_WRITABLE</flag>
+        </attr>
+        <attr>
+            <name>smfCampMaxRestart</name>
+            <type>SA_UINT32_T</type>
+            <category>SA_CONFIG</category>
+            <flag>SA_WRITABLE</flag>
+        </attr>
+        <attr>
+            <name>smfImmPersistCmd</name>
+            <type>SA_STRING_T</type>
+            <category>SA_CONFIG</category>
+            <flag>SA_WRITABLE</flag>
+        </attr>
+        <attr>
+            <name>smfNodeRebootCmd</name>
+            <type>SA_STRING_T</type>
+            <category>SA_CONFIG</category>
+            <flag>SA_WRITABLE</flag>OpenSafSmfConfig
+        </attr>
+        <attr>
+            <name>smfInactivatePbeDuringUpgrade</name>
+            <type>SA_UINT32_T</type>
+            <category>SA_CONFIG</category>
+            <flag>SA_WRITABLE</flag>
+        </attr>
+        <attr>
+            <name>smfVerifyEnable</name>
+            <type>SA_UINT32_T</type>
+            <category>SA_CONFIG</category>
+            <flag>SA_WRITABLE</flag>
+            <default-value>0</default-value>
+        </attr>
+        <attr>
+            <name>smfVerifyTimeout</name>
+            <type>SA_TIME_T</type>
+            <category>SA_CONFIG</category>
+            <flag>SA_WRITABLE</flag>
+            <default-value>100000000000</default-value>
+        </attr>
+        <attr>
+            <name>smfClusterControllers</name>
+            <type>SA_STRING_T</type>
+            <category>SA_CONFIG</category>
+            <flag>SA_WRITABLE</flag>
+            <flag>SA_MULTI_VALUE</flag>
+        </attr>
+        <attr>
+            <name>smfSSAffectedNodesEnable</name>
+            <type>SA_UINT32_T</type>
+            <category>SA_CONFIG</category>
+            <flag>SA_WRITABLE</flag>
+            <default-value>0</default-value>
+        </attr>
+        <attr>
+            <name>smfKeepDuState</name>
+            <type>SA_UINT32_T</type>
+            <category>SA_CONFIG</category>
+            <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>
+        <attr>
+            <name>smfProtectExecControlDuringInit</name>
+            <type>SA_UINT32_T</type>
+            <category>SA_CONFIG</category>
+            <flag>SA_WRITABLE</flag>
+            <default-value>0</default-value>
+        </attr>
+    </class>
+    <class name="OpenSafSmfCampRestartInfo">
+        <category>SA_RUNTIME</category>
+        <rdn>
+            <name>smfRestartInfo</name>
+            <type>SA_STRING_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+        </rdn>
+        <attr>
+            <name>smfCampRestartCnt</name>
+            <type>SA_UINT32_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+        </attr>
+    </class>
+    <class name="OpenSafSmfSingleStepInfo">
+        <category>SA_RUNTIME</category>
+        <rdn>
+            <name>smfSingleStepInfo</name>
+            <type>SA_STRING_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+        </rdn>
+        <attr>
+            <name>smfRebootType</name>
+            <type>SA_UINT32_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+        </attr>
+    </class>
+    <class name="OpenSafSmfCampRestartIndicator">
+        <category>SA_RUNTIME</category>
+        <rdn>
+            <name>smfCampaignRestartIndicator</name>
+            <type>SA_STRING_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+        </rdn>
+    </class>
+    <class name="OpenSafSmfPbeIndicator">
+        <category>SA_RUNTIME</category>
+        <rdn>
+            <name>safRdn</name>
+            <type>SA_STRING_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+        </rdn>
+    </class>
+    <class name="OpenSafSmfRollbackElement">
+        <category>SA_RUNTIME</category>
+        <rdn>
+            <name>smfRollbackElement</name>
+            <type>SA_STRING_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+        </rdn>
+    </class>
+    <class name="OpenSafSmfRollbackData">
+        <category>SA_RUNTIME</category>
+        <rdn>
+            <name>smfRollbackData</name>
+            <type>SA_STRING_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+        </rdn>
+        <attr>
+            <name>smfRollbackType</name>
+            <type>SA_STRING_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+        </attr>
+        <attr>
+            <name>smfRollbackDn</name>
+            <type>SA_NAME_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+        </attr>
+        <attr>
+            <name>smfRollbackClass</name>
+            <type>SA_STRING_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+        </attr>
+        <attr>
+            <name>smfRollbackAttrValue</name>
+            <type>SA_STRING_T</type>
+            <category>SA_RUNTIME</category>
+            <flag>SA_PERSISTENT</flag>
+            <flag>SA_CACHED</flag>
+            <flag>SA_MULTI_VALUE</flag>
+        </attr>
+    </class>
+    <class name="OpenSafSmfMisc">
+        <category>SA_CONFIG</category>
+        <rdn>
+            <name>openSafSmfMisc</name>
+            <type>SA_STRING_T</type>
+            <category>SA_CONFIG</category>
+            <flag>SA_INITIALIZED</flag>
+        </rdn>
+        <attr>
+            <name>reason</name>
+            <type>SA_STRING_T</type>
+            <category>SA_CONFIG</category>
+            <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>
+        <attr>
+            <name>numberOfSingleSteps</name>
+            <type>SA_UINT32_T</type>
+            <category>SA_CONFIG</category>
+            <flag>SA_WRITABLE</flag>
+        </attr>
+        <attr>
+            <name>nodesForSingleStep</name>
+            <type>SA_STRING_T</type>
+            <category>SA_CONFIG</category>
+            <flag>SA_WRITABLE</flag>
+            <flag>SA_MULTI_VALUE</flag>
+        </attr>
+    </class>
 </imm:IMM-contents>
diff --git a/osaf/services/saf/smfsv/smfd/Makefile.am 
b/osaf/services/saf/smfsv/smfd/Makefile.am
--- a/osaf/services/saf/smfsv/smfd/Makefile.am
+++ b/osaf/services/saf/smfsv/smfd/Makefile.am
@@ -49,7 +49,9 @@ noinst_HEADERS = \
        SmfCampaignWrapup.hh \
        SmfCampaignInit.hh \
        SmfCallback.hh \
-       SmfCbkUtil.hh
+       SmfCbkUtil.hh \
+       SmfExecControl.h \
+       SmfExecControlHdl.h
 
 osafsmfd_CXXFLAGS = $(AM_CXXFLAGS) @XML2_CFLAGS@
 
@@ -87,7 +89,9 @@ osafsmfd_SOURCES = \
        SmfCampaignInit.cc \
        SmfCampaignWrapup.cc \
        SmfCallback.cc \
-       SmfCbkUtil.cc
+       SmfCbkUtil.cc \
+       SmfExecControl.cc \
+       SmfExecControlHdl.cc
 
 osafsmfd_LDFLAGS = \
        $(AM_LDFLAGS) \
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
@@ -32,8 +32,10 @@
 #include "SmfCampaignThread.hh"
 #include "SmfCampaign.hh"
 #include "SmfProcedureThread.hh"
+#include "smfsv_defs.h"
 #include <immutil.h>
 #include <sstream>
+#include "SmfUpgradeAction.hh"
 /* ========================================================================
  *   DEFINITIONS
  * ========================================================================
@@ -268,6 +270,7 @@ SmfCampStateInitial::execute(SmfUpgradeC
        std::string s;
        std::stringstream out;
        SmfCampResultT initResult;
+        auto exechdl = i_camp->getExecControlHdl();
 
        TRACE("SmfCampStateInitial::execute implementation");
 
@@ -280,6 +283,9 @@ SmfCampStateInitial::execute(SmfUpgradeC
        if (prerequsitescheck(i_camp, error) != SA_AIS_OK) {
                goto exit_error;
        }
+        if (exechdl->smfProtectExecControlDuringInit(NULL)) {
+                exechdl->install();
+        }
 
        //Verify pre-check
        if (smfd_cb->smfVerifyEnable == SA_TRUE) {
@@ -338,10 +344,9 @@ SmfCampStateInitial::execute(SmfUpgradeC
                //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);
+                if (!exechdl->smfProtectExecControlDuringInit(NULL)) {
+                        exechdl->install();
+                }
 
                LOG_NO("SmfCampStateInitial::execute: startProcedureThreads()");
                 if 
(SmfCampaignThread::instance()->campaign()->startProcedureThreads() != 
SA_AIS_OK) {
@@ -757,19 +762,12 @@ 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.
 
-        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*> procedures = i_camp->getProcedures();
 
         std::vector < SmfUpgradeProcedure * >::iterator iter;
        bool execProcFound = false;
@@ -817,13 +815,7 @@ SmfCampStateExecuting::executeProc(SmfUp
        //The procedure vector is sorted in execution level order (low -> high)
        //Lowest number shall be executed first.
 
-        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*> procedures = i_camp->getProcedures();
        std::vector < SmfUpgradeProcedure * >::iterator iter;
        int execLevel = -1;
 
@@ -912,12 +904,7 @@ SmfCampStateExecuting::suspend(SmfUpgrad
        TRACE("SmfCampStateExecuting::suspend implementation");
 
        /* Send suspend message to all procedures */
-        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*> procedures = i_camp->getProcedures();
 
        std::vector < SmfUpgradeProcedure * >::iterator iter;
 
@@ -966,12 +953,7 @@ SmfCampStateExecuting::procResult(SmfUpg
                 LOG_NO("CAMP: Procedure %s returned STEPUNDONE", 
i_procedure->getProcName().c_str());
 
                 /* Send suspend message to all procedures */
-                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*> procedures = 
i_camp->getProcedures();
 
                std::vector < SmfUpgradeProcedure * >::iterator iter;
                for (iter = procedures.begin(); iter != procedures.end(); 
++iter) {
@@ -1114,21 +1096,8 @@ SmfCampStateExecCompleted::commit(SmfUpg
         i_camp->resetMaintenanceState(); // No action if it fails
 
         //Remove the procedure runtime objects
-       if (i_camp->getProcExecutionMode() == SMF_MERGE_TO_SINGLE_STEP) {
-                i_camp->getMergedProc()->commit();
-
-        } else {
-               std::vector < SmfUpgradeProcedure * > procedures;
-               if (i_camp->getProcExecutionMode() == SMF_MERGE_TO_SINGLE_STEP) 
{
-                       procedures.push_back(i_camp->getMergedProc());
-               } else {
-                       procedures = i_camp->getProcedures();
-               }
-
-                std::vector < SmfUpgradeProcedure * >::iterator iter;
-                for (iter = procedures.begin(); iter != procedures.end(); 
++iter) {
-                        (*iter)->commit();
-                }
+        for (auto proc: i_camp->getProcedures()) {
+            proc->commit();
         }
 
         i_camp->removeRunTimeObjects(); // No action if it fails
@@ -1209,16 +1178,7 @@ SmfCampStateSuspendingExec::execute(SmfU
        TRACE_ENTER();
        TRACE("SmfCampStateSuspendingExec::execute implementation");
 
-       //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*> procedures = i_camp->getProcedures();
 
        std::vector < SmfUpgradeProcedure * >::iterator iter;
        bool initialFound = false;
@@ -1353,17 +1313,8 @@ 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 */
-        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*> procedures = i_camp->getProcedures();
 
        std::vector < SmfUpgradeProcedure * >::iterator iter;
 
@@ -1423,12 +1374,7 @@ SmfCampStateExecSuspended::rollback(SmfU
        }
 
        /* Send rollback to all suspended procedures */
-        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*> procedures = i_camp->getProcedures();
 
        std::vector < SmfUpgradeProcedure * >::iterator iter;
 
@@ -1723,17 +1669,8 @@ 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 */
-        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*> procedures = i_camp->getProcedures();
 
        std::vector < SmfUpgradeProcedure * >::iterator iter;
 
@@ -1789,12 +1726,7 @@ SmfCampStateSuspendedByErrorDetected::ro
        }
 
        /* Send rollback to all suspended/undone procedures */
-        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*> procedures = i_camp->getProcedures();
 
        std::vector < SmfUpgradeProcedure * >::iterator iter;
 
@@ -1873,12 +1805,7 @@ SmfCampRollingBack::rollback(SmfUpgradeC
        TRACE_ENTER();
        TRACE("SmfCampRollingBack::rollback implementation");
 
-        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*> procedures = i_camp->getProcedures();
 
        std::vector < SmfUpgradeProcedure * >::reverse_iterator iter;
 
@@ -1960,12 +1887,7 @@ 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.
 
-        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*> procedures = i_camp->getProcedures();
 
        std::vector < SmfUpgradeProcedure * >::reverse_iterator iter;
 
@@ -2017,7 +1939,8 @@ SmfCampRollingBack::rollbackSingleMergeP
 {
        TRACE_ENTER();
        LOG_NO("CAMP:: Rollback merged single step procedure only");
-        SmfUpgradeProcedure * mergedProc = i_camp->getMergedProc();
+        std::vector<SmfUpgradeProcedure*> procedures = i_camp->getProcedures();
+        SmfUpgradeProcedure * mergedProc = procedures.at(0);
         if (mergedProc->getState() == SA_SMF_PROC_COMPLETED) {
                 SmfProcedureThread *procThread = mergedProc->getProcThread();
                 PROCEDURE_EVT *evt = new PROCEDURE_EVT();
@@ -2046,12 +1969,7 @@ SmfCampRollingBack::suspend(SmfUpgradeCa
        TRACE("SmfCampRollingBack::suspend implementation");
 
        /* Send suspend message to all procedures */
-        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*> procedures = i_camp->getProcedures();
 
        std::vector < SmfUpgradeProcedure * >::iterator iter;
 
@@ -2172,12 +2090,7 @@ SmfCampRollbackSuspended::rollback(SmfUp
        TRACE("SmfCampRollbackSuspended::rollback implementation");
 
        /* Send rollback to all suspended procedures */
-        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*> procedures = i_camp->getProcedures();
 
        std::vector < SmfUpgradeProcedure * >::iterator iter;
 
@@ -2345,16 +2258,8 @@ SmfCampRollbackCompleted::commit(SmfUpgr
         i_camp->resetMaintenanceState(); // No action if it fails
 
         //Remove the procedure runtime objects
-        if (i_camp->getProcExecutionMode() == SMF_MERGE_TO_SINGLE_STEP) {
-                i_camp->getMergedProc()->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();
-                }
+        for (auto proc: i_camp->getProcedures()) {
+            proc->commit();
         }
         
         i_camp->removeRunTimeObjects(); // No action if it fails
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
@@ -18,6 +18,7 @@
 #include <sys/stat.h>
 #include <new>
 #include <vector>
+#include <algorithm>
 #include <string>
 #include <sys/time.h>
 
@@ -30,7 +31,9 @@
 #include "SmfUpgradeProcedure.hh"
 #include "SmfUpgradeMethod.hh"
 #include "SmfProcedureThread.hh"
+#include "SmfUpgradeAction.hh"
 #include "SmfUtils.hh"
+#include "SmfExecControl.h"
 
 #include "saAis.h"
 #include <saSmf.h>
@@ -661,6 +664,10 @@ SmfCampaign::initExecution(void)
 SaAisErrorT
 SmfCampaign::startProcedureThreads()
 {
+        // If any procedure start goes badly two things happen: delete of the
+        // upgrade campaign pointer to terminate and remove previously started
+        // procedures. Return SA_AIS_OK to not change campaign state and allow
+        // reexecution
         TRACE_ENTER();
         SmfUpgradeCampaign *p_uc = getUpgradeCampaign();
         if (p_uc->getProcExecutionMode() == SMF_MERGE_TO_SINGLE_STEP) {
@@ -676,25 +683,25 @@ SmfCampaign::startProcedureThreads()
                 std::string singleProcDN = singleProc->getProcName() + "," +
                         SmfCampaignThread::instance()->campaign()->getDn();
                 singleProc->setDn(singleProcDN);
-                p_uc->setMergedProc(singleProc);
+                p_uc->addMergedProcedure(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 */
+                if (startProcedure(singleProc) == false) {
+                        delete p_uc;
                         return SA_AIS_OK;
                 }
+        } else if (p_uc->getProcExecutionMode() == SMF_BALANCED_MODE) {
+                if (!execctrl::createBalancedProcs()) {
+                        return SA_AIS_ERR_INIT;
+                }
+                auto procedures = p_uc->getProcedures();
+                TRACE("SmfCampaign::startProcedureThreads, number of 
procedures=[%zu]", procedures.size());
+                for (auto proc: procedures) {
+                        proc->setDn(proc->getProcName() + "," + 
SmfCampaignThread::instance()->campaign()->getDn());
+                        if (startProcedure(proc) == false) {
+                                delete p_uc;
+                                return SA_AIS_OK;
+                        }
+                }
         } else {
                 const std::vector < SmfUpgradeProcedure * >& procedures = 
p_uc->getProcedures();
                 std::vector < SmfUpgradeProcedure * >::const_iterator iter;
@@ -718,24 +725,10 @@ SmfCampaign::startProcedureThreads()
                         }
                         (*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 */
+                        if (startProcedure(*iter) == false) {
+                                delete p_uc;
                                 return SA_AIS_OK;
                         }
-
                         iter++;
                 }
         }
@@ -743,6 +736,26 @@ SmfCampaign::startProcedureThreads()
         return SA_AIS_OK; //Will never return here, just for compiler
 }
 
+//--------------------------------------------------------------------------
+// Starts one upgrade procedure thread, return false on failure
+//--------------------------------------------------------------------------
+bool
+SmfCampaign::startProcedure(SmfUpgradeProcedure* procedure) {
+        SmfProcedureThread *procedure_thread = new 
SmfProcedureThread(procedure);
+        // The procThread will set itself when started correctly
+        procedure->setProcThread(nullptr);
+        TRACE("SmfCampaign::startProcedure dn: %s", 
procedure->getDn().c_str());
+        procedure_thread->start();
+
+        if (procedure->getProcThread() == nullptr) {
+                std::string error = "Start of procedure thread failed for " + 
procedure->getDn();
+                LOG_ER("%s", error.c_str());
+                SmfCampaignThread::instance()->campaign()->setError(error);
+                return false;
+        }
+        return true;
+}
+
 /** 
  * 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
@@ -107,6 +107,7 @@ class SmfCampaign {
         void stopElapsedTime();
 
  private:
+        bool startProcedure(SmfUpgradeProcedure* procedure);
 
        std::string m_dn;
        std::string m_cmpg;
diff --git a/osaf/services/saf/smfsv/smfd/SmfExecControl.cc 
b/osaf/services/saf/smfsv/smfd/SmfExecControl.cc
new file mode 100644
--- /dev/null
+++ b/osaf/services/saf/smfsv/smfd/SmfExecControl.cc
@@ -0,0 +1,363 @@
+/*
+ *
+ * (C) Copyright 2009 The OpenSAF Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
+ * under the GNU Lesser General Public License Version 2.1, February 1999.
+ * The complete license can be accessed from the following location:
+ * http://opensource.org/licenses/lgpl-license.php
+ * See the Copying file included with the OpenSAF distribution for full
+ * licensing terms.
+ *
+ * Author(s): Ericsson AB
+ *
+ */
+
+#include "SmfExecControl.h"
+#include <list>
+#include <limits>
+#include <algorithm>
+#include "logtrace.h"
+#include "immutil.h"
+#include "SmfUpgradeProcedure.hh"
+#include "SmfUpgradeMethod.hh"
+#include "SmfUtils.hh"
+#include "SmfUpgradeAction.hh"
+#include "SmfUpgradeCampaign.hh"
+
+namespace execctrl {
+
+static std::vector<SmfUpgradeStep*> 
getStepsMatchingBalancedGroup(SmfUpgradeProcedure* procedure);
+
+static void addInitAndWrapupActionsToProcedure(SmfUpgradeProcedure* procedure,
+    const std::vector<SmfUpgradeAction*>& initactions,
+    const std::vector<SmfUpgradeAction*>& wrapupactions);
+
+static SmfUpgradeStep* mergeStep(SmfUpgradeProcedure* procedure,
+    const std::vector<SmfUpgradeStep*>& steps);
+
+static bool removeDuplicateActivationUnits(SmfUpgradeProcedure * i_newproc,
+                                    SmfUpgradeStep *newStep);
+
+
+static bool isNodeInGroup(const std::string& node,
+                          const std::vector<std::string>& group) {
+  return std::find(group.begin(), group.end(), node) != group.end();
+}
+
+bool createBalancedProcs() {
+  // Creates new procedures based on the ExecControl configuration
+  TRACE_ENTER();
+  auto ucamp = SmfCampaignThread::instance()->campaign()->getUpgradeCampaign();
+  auto exechdl = ucamp->getExecControlHdl();
+
+  bool errinfo = false;
+  auto numberofss = exechdl->numberOfSingleSteps(&errinfo);
+  if (errinfo == false) {
+    TRACE("Failed reading attribute from ExecControlHdl");
+    return false;
+  }
+  // Assume that nodesForSingleStep only contains nodes used by the campaign.
+  auto nodesforss = exechdl->nodesForSingleStep(&errinfo);
+  if (errinfo == false) {
+    TRACE("Failed reading attribute from ExecControlHdl");
+    return false;
+  }
+  for (auto& node : nodesforss) {
+    node = "safAmfNode=" + std::string(node) + ",safAmfCluster=myAmfCluster";
+  }
+  std::vector<SmfUpgradeProcedure*> balancedprocs;
+  // chunk is the size of the balanced group
+  unsigned int chunk = (nodesforss.size() + numberofss - 1) / numberofss;
+  TRACE("balanced group size will be %i", chunk);
+  std::vector<std::string>::iterator itr;
+  std::vector<std::string>::iterator iend;
+  // Set the procedure exec level to be as high as possible
+  int procExecLvl = std::numeric_limits<int>::max() - numberofss - 1;
+  int procnum = 0;
+  for (itr = nodesforss.begin(); iend < nodesforss.end(); itr += chunk) {
+    iend = itr + chunk;
+    SmfUpgradeProcedure *ssproc = new(std::nothrow) SmfUpgradeProcedure;
+    if (iend >= nodesforss.end()) {
+      iend = nodesforss.end();
+    }
+    ssproc->setUpgradeMethod(new(std::nothrow) SmfSinglestepUpgrade);
+    ssproc->setProcName("safSmfProc=SmfBalancedProc" + 
std::to_string(procnum));
+    ssproc->setExecLevel(std::to_string(procExecLvl));
+    ssproc->setIsMergedProcedure(true);  // For cleanup purposes
+    // Each new procedure holds the balanced group it steps over
+    ssproc->setBalancedGroup(std::vector<std::string>(itr, iend));
+    balancedprocs.push_back(ssproc);
+    procExecLvl++;
+    procnum++;
+  }
+  for (auto proc : balancedprocs) {
+      ucamp->addUpgradeProcedure(proc);
+  }
+  TRACE_LEAVE();
+  return true;
+}
+
+bool createStepForBalancedProc(SmfUpgradeProcedure* procedure) {
+  TRACE_ENTER();
+  std::vector<SmfUpgradeStep*> steps;
+  std::vector<SmfUpgradeAction*> initactions;
+  std::vector<SmfUpgradeAction*> wrapupactions;
+  for (auto step : getStepsMatchingBalancedGroup(procedure)) {
+    // copy the steps together with actions and callbacks
+    auto oproc = step->getProcedure();
+    steps.insert(steps.end(),
+                 oproc->getProcSteps().begin(),
+                 oproc->getProcSteps().end());
+    initactions.insert(initactions.end(),
+                       oproc->getInitActions().begin(),
+                       oproc->getInitActions().end());
+    wrapupactions.insert(wrapupactions.end(),
+                         oproc->getWrapupActions().begin(),
+                         oproc->getWrapupActions().end());
+    procedure->getCallbackList(oproc->getUpgradeMethod());
+  }
+  if (!steps.empty()) {
+    SmfUpgradeStep* newstep = mergeStep(procedure, steps);
+    addInitAndWrapupActionsToProcedure(procedure, initactions, wrapupactions);
+    removeDuplicateActivationUnits(procedure, newstep);
+    procedure->addProcStep(newstep);
+  }
+  TRACE_LEAVE();
+  return true;
+}
+
+bool allStepsMerged(SmfUpgradeProcedure* procedure) {
+  TRACE_ENTER();
+  if (!procedure->getBalancedGroup().empty()) {
+    TRACE("not an original proc");
+    return false;
+  }
+  auto camp = SmfCampaignThread::instance()->campaign();
+  auto allprocs = camp->getUpgradeCampaign()->getProcedures();
+
+  auto nodesforss = 
camp->getUpgradeCampaign()->getExecControlHdl()->nodesForSingleStep(NULL);
+  for (auto& node : nodesforss) {
+    node = "safAmfNode=" + std::string(node) + ",safAmfCluster=myAmfCluster";
+  }
+
+  bool allmerged = true;
+  for (auto step : procedure->getProcSteps()) {
+    if (!isNodeInGroup(step->getSwNode(), nodesforss)) {
+      TRACE("node not in group stepNode:%s", step->getSwNode().c_str());
+      allmerged = false;
+    } else {
+      TRACE("node in group stepNode:%s", step->getSwNode().c_str());
+      step->setStepState(SA_SMF_STEP_COMPLETED);
+    }
+  }
+  TRACE("allStepsMerged returns:%d", allmerged);
+  TRACE_LEAVE();
+  return allmerged;
+}
+
+void trace(const std::string& message) {
+  TRACE("-tracing procedures in UpgradeCampaign:%s", message.c_str());
+  auto camp = SmfCampaignThread::instance()->campaign();
+  for (auto proc : camp->getUpgradeCampaign()->getProcedures()) {
+    TRACE("-procedure: name:%s dn:%s", proc->getName().c_str(), 
proc->getDn().c_str());
+    for (auto step : proc->getProcSteps()) {
+      TRACE("    -step : %s, state %i", step->getDn().c_str(), 
step->getState());
+    }
+    for (auto node : proc->getBalancedGroup()) {
+      TRACE("    balanced node : %s", node.c_str());
+    }
+    for (auto iact : proc->getInitActions()) {
+      auto cba = dynamic_cast<SmfCallbackAction*>(iact);
+      TRACE("    iact cb label : %s", 
cba->getCallback().getCallbackLabel().c_str());
+    }
+  }
+}
+
+std::vector<SmfUpgradeStep*> getStepsMatchingBalancedGroup(
+    SmfUpgradeProcedure* procedure) {
+  TRACE_ENTER();
+  // For all original procedures check if the steps are in the balanced group
+  // of the procedure. Return the matching steps.
+  std::vector<SmfUpgradeStep*> steps;
+  auto camp = SmfCampaignThread::instance()->campaign();
+  for (auto proc : camp->getUpgradeCampaign()->getProcedures()) {
+    if (proc->getBalancedGroup().empty()) {
+      for (auto ostep : proc->getProcSteps()) {
+        if (isNodeInGroup(ostep->getSwNode(), procedure->getBalancedGroup())) {
+          TRACE("step in group: %s", ostep->getDn().c_str());
+          steps.push_back(ostep);
+        } else {
+          TRACE("step not in group: %s", ostep->getDn().c_str());
+        }
+      }
+    }
+  }
+  TRACE_LEAVE();
+  return steps;
+}
+
+void addInitAndWrapupActionsToProcedure(SmfUpgradeProcedure* procedure,
+    const std::vector<SmfUpgradeAction*>& initactions,
+    const std::vector<SmfUpgradeAction*>& wrapupactions) {
+  // Add Init/WrapupActions to the procedure. The Actions themself contain a
+  // pointer to the procedure.
+  TRACE_ENTER();
+  procedure->addInitActions(initactions);
+  procedure->addWrapupActions(wrapupactions);
+  for (auto iac : initactions) {
+    const SmfCallbackAction* cba = dynamic_cast<const SmfCallbackAction*>(iac);
+    if (cba != nullptr) {
+      const_cast<SmfCallbackAction*>(cba)->setCallbackProcedure(procedure);
+    }
+  }
+  for (auto wac : wrapupactions) {
+    const SmfCallbackAction* cba = dynamic_cast<const SmfCallbackAction*>(wac);
+    if (cba != nullptr) {
+      const_cast<SmfCallbackAction*>(cba)->setCallbackProcedure(procedure);
+    }
+  }
+  TRACE_LEAVE();
+}
+
+SmfUpgradeStep* mergeStep(SmfUpgradeProcedure* procedure,
+    const std::vector<SmfUpgradeStep*>& steps) {
+  // Create a merged step based on the upgrade step passed in. The in/out
+  // parameter procedure must be a balanced procedure.
+  TRACE_ENTER();
+  SmfUpgradeStep* newstep = new(std::nothrow)SmfUpgradeStep;
+  osafassert(newstep != nullptr);
+  newstep->setRdn("safSmfStep=0001");
+  newstep->setDn(newstep->getRdn() + "," + procedure->getDn());
+  newstep->setMaxRetry(0);
+  newstep->setRestartOption(0);
+  std::list <unitNameAndState> deact;
+  for (auto step : steps) {
+    if (isNodeInGroup(step->getSwNode(), procedure->getBalancedGroup())) {
+      TRACE("adding modifications, deact and bundle ref from node:%s",
+            step->getSwNode().c_str());
+      newstep->addModifications(step->getModifications());
+      deact.insert(deact.end(),
+                   step->getDeactivationUnitList().begin(),
+                   step->getDeactivationUnitList().end());
+      procedure->mergeBundleRefRollingToSingleStep(newstep, step);
+    }
+  }
+  TRACE_LEAVE();
+  return newstep;
+}
+
+bool removeDuplicateActivationUnits(SmfUpgradeProcedure * i_newproc,
+                                                SmfUpgradeStep *newStep) {
+  // Remove any (de)activation unit duplicates and add them to the step.
+  // Activation and deactivation units are the same because rolling and
+  // formodify is symetric.
+  TRACE_ENTER();
+  std::list < unitNameAndState > tmpDU;
+  std::multimap<std::string, objectInst> objInstances;
+  if (i_newproc->getImmComponentInfo(objInstances) == false) {
+    TRACE("Config info from IMM could not be read");
+    return false;
+  }
+
+  // Remove DU duplicates
+  tmpDU.sort(compare_du_part);
+  tmpDU.unique(unique_du_part);
+
+  // Reduce the DU list, check if smaller scope is within bigger scope.
+  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
+      // A node will never be optimized away, save it
+      nodeLevelDU.push_back(*unit_iter);
+      // Remove the node and update iterator
+      unit_iter = tmpDU.erase(unit_iter);
+    } 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 itr;
+  for (itr = nodeLevelDU.begin(); itr != nodeLevelDU.end(); ++itr) {
+    // For all comp/SU found in the scope of the node.  Find out if any
+    // remaining DU is within it.
+    // Get all components/SU within the node
+    nodeName_mm = objInstances.equal_range((*itr).name);
+    for (iter = nodeName_mm.first;  iter != nodeName_mm.second;  ++iter) {
+      // For all comp/SU found in the scope of the node.
+      // Find out if any remaining DU is within it
+      for (unit_iter = tmpDU.begin(); unit_iter != tmpDU.end();) {
+        if ((*unit_iter).name == (*iter).second.suDN) {  // Check SU
+          TRACE("[%s] is in scope of [%s], remove it from DU list",
+                 (*unit_iter).name.c_str(), (*itr).name.c_str());
+          // Remove the node and update iterator
+          unit_iter = tmpDU.erase(unit_iter);
+        } else if ((*unit_iter).name == (*iter).second.compDN) {  // Check comp
+          TRACE("[%s] is in scope of [%s], remove it from DU list",
+                 (*unit_iter).name.c_str(), (*itr).name.c_str());
+          // Remove the node and update iterator
+          unit_iter = tmpDU.erase(unit_iter);
+        } 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
+      // A node will never be optimized away, save it
+      suLevelDU.push_back(*unit_iter);
+      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
+        TRACE("[%s] is in scope of [%s], remove it from DU list",
+              (*unit_iter).name.c_str(), (*su_iter).name.c_str());
+        // Remove the Component and update iterator
+        unit_iter = tmpDU.erase(unit_iter);
+      } 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
+
+  // Rolling and forModify are symetric, add the node level DU
+  newStep->addActivationUnits(nodeLevelDU);
+  // Rolling and forModify are symetric, Add the SU level DU
+  newStep->addActivationUnits(suLevelDU);
+  // Rolling and forModify are symetric, Add the comp level DU
+  newStep->addActivationUnits(tmpDU);
+
+  TRACE_LEAVE();
+  return true;
+}
+
+} // namespace execctrl
diff --git a/osaf/services/saf/smfsv/smfd/SmfExecControl.h 
b/osaf/services/saf/smfsv/smfd/SmfExecControl.h
new file mode 100644
--- /dev/null
+++ b/osaf/services/saf/smfsv/smfd/SmfExecControl.h
@@ -0,0 +1,59 @@
+/*
+ *
+ * (C) Copyright 2016 The OpenSAF Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
+ * under the GNU Lesser General Public License Version 2.1, February 1999.
+ * The complete license can be accessed from the following location:
+ * http://opensource.org/licenses/lgpl-license.php
+ * See the Copying file included with the OpenSAF distribution for full
+ * licensing terms.
+ *
+ * Author(s): Ericsson AB
+ *
+ */
+#ifndef OPENSAF_STAGING_OSAF_SERVICES_SAF_SMFSV_SMFD_SMFEXECCONTROL_H_
+#define OPENSAF_STAGING_OSAF_SERVICES_SAF_SMFSV_SMFD_SMFEXECCONTROL_H_
+
+#include <vector>
+#include <string>
+#include "base/macros.h"
+#include "SmfUpgradeStep.hh"
+#include "SmfUpgradeAction.hh"
+#include "saAis.h"
+
+/*
+ * These set of functions enables the balanced mode feature. This mode changes
+ * the execution of rolling procedures to be merged into one or several single
+ * steps that are spread out across the cluster nodes. This feature is used to
+ * give a faster upgrade time compared to rolling one node at a time, possibly
+ * several times for each node. By splitting the procedures it into several
+ * single steps across the nodes a total service outage can be avoided.
+ */
+namespace execctrl {
+  /*
+   * Creates empty procedures with the configuration provided in the
+   * ExecControl object. The Campaign object need these empty procedures to
+   * spawn procedure threads. Once started the steps will be built and added to
+   * the procedure.
+   */
+  bool createBalancedProcs();
+  /*
+   * Create the merged step for a balanced procedure. This merged step is based
+   * on steps from original procedures matching the balanced group.
+   */
+  bool createStepForBalancedProc(SmfUpgradeProcedure* procedure);
+  /*
+   * Check if an original procedure will have all its steps merged to balanced
+   * procedures. Set the step that will be merged to completed state.
+   *
+   * Return: true, if all steps will be merged
+   */
+  bool allStepsMerged(SmfUpgradeProcedure* procedure);
+
+  void trace(const std::string& message);
+} // namespace execctrl
+
+#endif  // OPENSAF_STAGING_OSAF_SERVICES_SAF_SMFSV_SMFD_SMFEXECCONTROL_H_
diff --git a/osaf/services/saf/smfsv/smfd/SmfExecControlHdl.cc 
b/osaf/services/saf/smfsv/smfd/SmfExecControlHdl.cc
new file mode 100644
--- /dev/null
+++ b/osaf/services/saf/smfsv/smfd/SmfExecControlHdl.cc
@@ -0,0 +1,506 @@
+/*
+ *
+ * (C) Copyright 2009 The OpenSAF Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
+ * under the GNU Lesser General Public License Version 2.1, February 1999.
+ * The complete license can be accessed from the following location:
+ * http://opensource.org/licenses/lgpl-license.php
+ * See the Copying file included with the OpenSAF distribution for full
+ * licensing terms.
+ *
+ * Author(s): Ericsson AB
+ *
+ */
+
+#include "SmfExecControlHdl.h"
+
+#include <string>
+#include <vector>
+
+#include "osaf_extended_name.h"
+#include "saAis.h"
+#include "saf_error.h"
+#include "immutil.h"
+#include "SmfUtils.hh"
+#include "SmfCampaign.hh"
+
+// Note: Info about public methods can be found in .h file
+
+SmfExecControlObjHandler::SmfExecControlObjHandler() :
+  m_smfProtectExecControlDuringInit(0),
+  m_smfProtectExecControlDuringInit_valid(false),
+  m_procExecMode(0),
+  m_procExecMode_valid(false),
+  m_numberOfSingleSteps(0),
+  m_numberOfSingleSteps_valid(false),
+  m_nodesForSingleStep_valid(false),
+  m_attributes(0),
+  m_exec_ctrl_name_ad(0),
+  m_procExecMode_ad(0),
+  m_numberOfSingleSteps_ad(0),
+  m_nodesForSingleStep_ad(0)
+{
+  p_immutil_object = new SmfImmUtils; // Deleted by uninstall and in destructor
+}
+
+SmfExecControlObjHandler::~SmfExecControlObjHandler() {
+  // Note 1:
+  // The exec control object copy cannot be removed here since it may
+  // be needed after restart or SI-swap. Use uninstall() to cleanup and remove
+  // the exec control object copy.
+  // Note 2:
+  // If the exec control object copy is not removed it will remain as a "stray"
+  // IMM object, however this is not a resource leek since it will be
+  // overwritten the next time a copy has to be created
+  //
+  TRACE_ENTER();
+  if (p_immutil_object != 0)
+    delete p_immutil_object;
+  TRACE_LEAVE();
+}
+
+bool SmfExecControlObjHandler::install() {
+  TRACE_ENTER();
+
+  // Read smf configuration data needed for handling exec control
+  //
+  if (readOpenSafSmfConfig() == false) {
+    LOG_NO("%s: readOpenSafSmfConfig Fail", __FUNCTION__);
+    return false;
+  }
+
+  // Read the original exec control object and save attribute values in member
+  // variables and handle valid flags.
+  // 
+  const char* exec_ctrl_name = c_openSafSmfExecControl;
+  if (readExecControlObject(exec_ctrl_name) == false) {
+    LOG_NO("%s: readExecControlObject Fail", __FUNCTION__);
+    return false;
+  }
+
+  // Create a copy of the exec control object. If already exist it's 
overwritten
+  removeExecControlObjectCopy();
+  if (copyExecControlObject() == false) {
+    LOG_NO("%s: copyExecControlObject Fail", __FUNCTION__);
+    return false;
+  }
+
+  TRACE_LEAVE();
+  return true;
+}
+
+void SmfExecControlObjHandler::uninstall() {
+  TRACE_ENTER();
+  if (p_immutil_object != 0)
+    delete p_immutil_object;
+  removeExecControlObjectCopy();
+  TRACE_LEAVE();
+}
+
+SaUint32T SmfExecControlObjHandler::procExecMode(bool *errinfo) {
+  TRACE_ENTER();
+  bool i_errinfo = true; //No error
+
+  if (m_procExecMode_valid == false) {
+    TRACE("%s has no valid value, try to read the IMM copy",__FUNCTION__);
+    i_errinfo = getValuesFromImmCopy();
+  }
+
+  if (errinfo != NULL) {
+    *errinfo = i_errinfo;
+  }
+
+  TRACE_LEAVE();
+  return m_procExecMode;
+}
+
+SaUint32T SmfExecControlObjHandler::numberOfSingleSteps(bool *errinfo) {
+  TRACE_ENTER();
+  bool i_errinfo = true; //No error
+
+  if (m_numberOfSingleSteps_valid == false) {
+    TRACE("%s has no valid value, try to read the IMM copy",__FUNCTION__);
+    i_errinfo = getValuesFromImmCopy();
+  }
+
+  if (errinfo != NULL) {
+    *errinfo = i_errinfo;
+  }
+
+  TRACE_LEAVE();
+  return m_numberOfSingleSteps;
+}
+
+std::vector <std::string> SmfExecControlObjHandler::nodesForSingleStep
+  (bool *errinfo) {
+  TRACE_ENTER();
+  bool i_errinfo = true; //No error
+
+  if (m_nodesForSingleStep_valid == false) {
+    TRACE("%s has no valid value, try to read the IMM copy",__FUNCTION__);
+    i_errinfo = getValuesFromImmCopy();
+  }
+
+  if (errinfo != NULL) {
+    *errinfo = i_errinfo;
+  }
+
+  TRACE_LEAVE();
+  return m_nodesForSingleStep;
+}
+
+bool SmfExecControlObjHandler::smfProtectExecControlDuringInit(
+  bool *errinfo=NULL) {
+  TRACE_ENTER();
+  bool i_errinfo = true;
+
+  if (m_smfProtectExecControlDuringInit_valid == false) {
+    i_errinfo = readOpenSafSmfConfig();
+  }
+
+  if (errinfo != NULL) {
+    *errinfo = i_errinfo;
+  }
+
+  if (m_smfProtectExecControlDuringInit > 0) {
+    return true;
+  } else {
+    return false;
+  }
+}
+
+
+/**
+ * Read all values from the exec control object copy if one exist
+ * 
+ * @return
+ */
+bool SmfExecControlObjHandler::getValuesFromImmCopy() {
+  bool errinfo = true;
+
+  TRACE_ENTER();
+    if (readExecControlObject(c_openSafSmfExecControl_copy) == false) {
+      LOG_NO("%s readExecControlObject(c_openSafSmfExecControl_copy) Fail",
+             __FUNCTION__);
+      errinfo = false;
+    }
+
+  TRACE_LEAVE();
+  return errinfo;
+}
+
+/**
+ * Read the exec control object and save its values into member variables
+ * The attribute descriptors are saved so that a copy can be made
+ * 
+ * @return false on Fail
+ */
+bool SmfExecControlObjHandler::readExecControlObject
+  (const char* exec_ctrl_name) {
+  TRACE_ENTER();
+
+  TRACE("%s: Name of exec control object '%s'",
+        __FUNCTION__, exec_ctrl_name);
+
+  // Get all attributes of the exec control object
+  if (p_immutil_object->getObject(exec_ctrl_name, &m_attributes) == false) {
+    TRACE("%s: Failed to get object from attribute %s",
+           __FUNCTION__, OPENSAF_SMF_EXEC_CONTROL);
+    return false;
+  }
+
+  // Store all existing attributes in member variables. Ignore if not existing
+  // attribute and keep variable default value
+  // Values are not validated here
+
+  saveAttributeDescriptors();
+
+  const SaUint32T* p_procExecMode = immutil_getUint32Attr(
+    (const SaImmAttrValuesT_2 **) m_attributes, "procExecMode", 0);
+  if (p_procExecMode == 0) {
+    LOG_NO("%s: Could not read procExecMode", __FUNCTION__);
+  } else {
+    m_procExecMode = *p_procExecMode;
+    m_procExecMode_valid = true;
+  }
+  
+  const SaUint32T* p_numberOfSingleSteps = immutil_getUint32Attr(
+    (const SaImmAttrValuesT_2 **) m_attributes, "numberOfSingleSteps", 0);
+  if (p_numberOfSingleSteps == 0) {
+    LOG_NO("%s: Could not read numberOfSingleSteps", __FUNCTION__);
+  } else {
+    m_numberOfSingleSteps = *p_numberOfSingleSteps;
+    m_numberOfSingleSteps_valid = true;
+  }
+
+  // Fill in node name vector
+  SaAisErrorT ais_rc;
+  SaUint32T number_of_nodes;
+  ais_rc = immutil_getAttrValuesNumber(const_cast<char*> 
("nodesForSingleStep"),
+                                   (const SaImmAttrValuesT_2 **) m_attributes,
+                                   &number_of_nodes);
+  if (ais_rc != SA_AIS_OK) {
+    LOG_NO("%s: No nodesForSingleStep found", __FUNCTION__);
+    return true;
+  }
+
+  const char* p_node_name;
+  for (unsigned int i = 0; i < number_of_nodes; i++) {
+    p_node_name =immutil_getStringAttr(
+        (const SaImmAttrValuesT_2**) m_attributes,
+        "nodesForSingleStep", i);
+    if (p_node_name == NULL) {
+      break;
+    }
+    m_nodesForSingleStep.push_back(p_node_name);
+    m_nodesForSingleStep_valid = true;
+  }
+
+  TRACE_LEAVE();
+  return true;
+}
+/**
+ * Read the smf config object and save openSafSmfExecControl and
+ * smfProtectExecControlDuringInit
+ *
+ * @return false on fail
+ */
+bool SmfExecControlObjHandler::readOpenSafSmfConfig() {
+  // Get the name of the exec control object
+  if (p_immutil_object->getObject(SMF_CONFIG_OBJECT_DN, &m_attributes) == 
false) {
+    LOG_WA("%s: Could not get SMF config object from IMM %s",
+           __FUNCTION__, SMF_CONFIG_OBJECT_DN);
+    return "";
+  }
+
+  const char* exec_ctrl_name = immutil_getStringAttr(
+    (const SaImmAttrValuesT_2 **) m_attributes, OPENSAF_SMF_EXEC_CONTROL, 0);
+  if (exec_ctrl_name == NULL || strcmp(exec_ctrl_name, "") == 0) {
+    LOG_WA("%s: Could not get %s attrs from SmfConfig",
+           __FUNCTION__, OPENSAF_SMF_EXEC_CONTROL);
+    return "";
+  }
+  c_openSafSmfExecControl = exec_ctrl_name;
+
+  const SaUint32T* p_protect_flag = immutil_getUint32Attr(
+    (const SaImmAttrValuesT_2 **) m_attributes,
+    "smfProtectExecControlDuringInit", 0);
+  if (p_protect_flag == NULL) {
+    LOG_ER("could not read smfProtectExecControlDuringInit");
+    return false;
+  }
+  m_smfProtectExecControlDuringInit = *p_protect_flag;
+  m_smfProtectExecControlDuringInit_valid = true;
+
+  return true;
+}
+
+/**
+ * Delete the exec control object copy if exist
+ */
+void SmfExecControlObjHandler::removeExecControlObjectCopy() {
+  SaAisErrorT ais_rc = SA_AIS_OK;
+
+  TRACE_ENTER();
+  SaNameT node_name;
+  osaf_extended_name_lend(c_openSafSmfExecControl_copy,
+          &node_name);
+
+  TRACE("Deleting object '%s'", c_openSafSmfExecControl_copy);
+
+  ais_rc = immutil_saImmOmCcbObjectDelete(m_ccbHandle,
+          &node_name);
+  if (ais_rc != SA_AIS_OK) {
+          LOG_NO("%s: saImmOmCcbObjectDelete '%s' Fail %s",
+           __FUNCTION__, c_openSafSmfExecControl_copy,
+           saf_error(ais_rc));
+  } else {
+          ais_rc = saImmOmCcbApply(m_ccbHandle);
+          if (ais_rc != SA_AIS_OK) {
+          LOG_NO("%s: saImmOmCcbApply() Fail '%s'",
+                  __FUNCTION__, saf_error(ais_rc));
+          }
+  }
+
+  TRACE_LEAVE();
+}
+
+/**
+ * Create a copy of the exec control object. The exec control object must have
+ * been read before a copy can be made.
+ *
+ * @return false on fail
+ */
+bool SmfExecControlObjHandler::copyExecControlObject() {
+  bool rc = true;
+
+  TRACE_ENTER();
+
+  SaAisErrorT ais_rc = SA_AIS_OK;
+
+  // ------------------------------------
+  // Create handles needed
+  //
+  rc = createAllImmHandles();
+  if (rc == false) {
+    LOG_NO("%s: createAllImmHandles Fail", __FUNCTION__);
+    return rc;
+  }
+
+  // ------------------------------------
+  // A new attribute descriptor for the node
+  // name has to be created
+  // Attribute: openSafSmfExecControl
+  //
+  SaImmAttrValuesT_2 smfExecControl_copy_ad;
+  smfExecControl_copy_ad.attrName =
+      const_cast<SaImmAttrNameT> ("openSafSmfExecControl");
+  smfExecControl_copy_ad.attrValueType = SA_IMM_ATTR_SASTRINGT;
+  char *object_name = const_cast<char *> (c_openSafSmfExecControl_copy);
+  smfExecControl_copy_ad.attrValuesNumber = 1;
+  SaImmAttrValueT object_names[] = {&object_name};
+  smfExecControl_copy_ad.attrValues = object_names;
+
+
+  // ------------------------------------
+  // NULL terminated array of pointers to the list of attributes.
+  // In this case only one attribute, saAmfNGNodeListAttr
+  const SaImmAttrValuesT_2 *attrValues[] = {
+    &smfExecControl_copy_ad,
+    m_procExecMode_ad,
+    m_numberOfSingleSteps_ad,
+    m_nodesForSingleStep_ad,
+    NULL
+  };
+
+  // ---------------------------------------
+  // Create the node group. Top level object
+  SaImmClassNameT className = const_cast<SaImmClassNameT> (c_class_name);
+  ais_rc = immutil_saImmOmCcbObjectCreate_2(
+              m_ccbHandle,
+              className,
+              NULL,
+              attrValues);
+
+  if (ais_rc != SA_AIS_OK) {
+    LOG_NO("%s: saImmOmCcbObjectCreate_2() '%s' Fail %s",
+           __FUNCTION__, object_name, saf_error(ais_rc));
+    rc = false;
+  } else {
+    ais_rc = saImmOmCcbApply(m_ccbHandle);
+    if (ais_rc != SA_AIS_OK) {
+      LOG_NO("%s: saImmOmCcbApply() Fail '%s'",
+             __FUNCTION__, saf_error(ais_rc));
+      rc = false;
+    }
+  }
+
+  TRACE_LEAVE();
+  return rc;
+}
+
+/**
+ * Save attribute descriptors for all attributes needed to create a copy
+ * of the exec control object
+ */
+void SmfExecControlObjHandler::saveAttributeDescriptors() {
+  TRACE_ENTER();
+  for (int i = 0; m_attributes[i] != NULL; i++) {
+    if (strcmp(m_attributes[i]->attrName, "openSafSmfExecControl") == 0) {
+      m_exec_ctrl_name_ad = m_attributes[i];
+    } else if (strcmp(m_attributes[i]->attrName, "procExecMode") == 0) {
+      m_procExecMode_ad = m_attributes[i];
+    } else if (strcmp(m_attributes[i]->attrName, "numberOfSingleSteps") == 0) {
+      m_numberOfSingleSteps_ad = m_attributes[i];
+    } else if (strcmp(m_attributes[i]->attrName, "nodesForSingleStep") == 0) {
+      m_nodesForSingleStep_ad = m_attributes[i];
+    }
+  }
+  TRACE_LEAVE();
+}
+/**
+ * Get all needed IMM handles and store them in member variables
+ * NOTE: This is a copy of a method in the SmfAdminOperation class.
+ *       This should be fixed
+ * 
+ * @return false on Fail
+ */
+bool SmfExecControlObjHandler::createAllImmHandles() {
+  SaAisErrorT ais_rc = SA_AIS_ERR_TRY_AGAIN;
+  int timeout_try_cnt = 6;
+  bool rc = true;
+
+  TRACE_ENTER();
+  // OM handle
+  while (timeout_try_cnt > 0) {
+    ais_rc = immutil_saImmOmInitialize(&m_omHandle, NULL,
+                                       &m_immVersion);
+    if (ais_rc != SA_AIS_ERR_TIMEOUT)
+      break;
+    timeout_try_cnt--;
+  }
+  if (ais_rc != SA_AIS_OK) {
+    LOG_NO("%s: saImmOmInitialize Fail %s", __FUNCTION__,
+           saf_error(ais_rc));
+    rc = false;
+  }
+
+  // Accessors handle
+  if (rc == true) {
+    timeout_try_cnt = 6;
+    while (timeout_try_cnt > 0) {
+      ais_rc = immutil_saImmOmAccessorInitialize(m_omHandle,
+                                                 &m_accessorHandle);
+      if (ais_rc != SA_AIS_ERR_TIMEOUT)
+        break;
+      timeout_try_cnt--;
+    }
+    if (ais_rc != SA_AIS_OK) {
+      LOG_NO("%s: saImmOmAccessorInitialize Fail %s",
+             __FUNCTION__, saf_error(ais_rc));
+      rc = false;
+    }
+  }
+
+  // Admin owner handle
+  if (rc == true) {
+    timeout_try_cnt = 6;
+    while (timeout_try_cnt > 0) {
+      ais_rc = immutil_saImmOmAdminOwnerInitialize(m_omHandle,
+                                                   const_cast<char*>
+                                                   
("SmfExecControlObjHandlerOwner"),
+                                                   SA_TRUE, &m_ownerHandle);
+      if (ais_rc != SA_AIS_ERR_TIMEOUT)
+        break;
+      timeout_try_cnt--;
+    }
+    if (ais_rc != SA_AIS_OK) {
+      LOG_NO("%s: saImmOmAdminOwnerInitialize Fail %s",
+             __FUNCTION__, saf_error(ais_rc));
+      rc = false;
+    }
+  }
+
+  // CCB handle
+  if (rc == true) {
+    timeout_try_cnt = 6;
+    while (timeout_try_cnt > 0) {
+      ais_rc = immutil_saImmOmCcbInitialize(m_ownerHandle,
+                                            0, &m_ccbHandle);
+      if (ais_rc != SA_AIS_ERR_TIMEOUT)
+        break;
+      timeout_try_cnt--;
+    }
+    if (ais_rc != SA_AIS_OK) {
+      LOG_NO("%s: saImmOmCcbInitialize Fail %s",
+             __FUNCTION__, saf_error(ais_rc));
+      rc = false;
+    }
+  }
+
+  TRACE_LEAVE();
+  return rc;
+}
diff --git a/osaf/services/saf/smfsv/smfd/SmfExecControlHdl.h 
b/osaf/services/saf/smfsv/smfd/SmfExecControlHdl.h
new file mode 100644
--- /dev/null
+++ b/osaf/services/saf/smfsv/smfd/SmfExecControlHdl.h
@@ -0,0 +1,126 @@
+/*
+ *
+ * (C) Copyright 2016 The OpenSAF Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
+ * under the GNU Lesser General Public License Version 2.1, February 1999.
+ * The complete license can be accessed from the following location:
+ * http://opensource.org/licenses/lgpl-license.php
+ * See the Copying file included with the OpenSAF distribution for full
+ * licensing terms.
+ *
+ * Author(s): Ericsson AB
+ *
+ */
+
+#ifndef SMFEXECCONTROLHDL_H
+#define SMFEXECCONTROLHDL_H
+
+#include <string>
+#include <vector>
+
+#include "saAis.h"
+#include "base/macros.h"
+#include "saImmOm.h"
+#include "SmfUtils.hh"
+
+/*
+ * Handler for the OpenSafSmfExecControl IMM object. An object of this class 
can
+ * read all information in an exec control object and has methods for making
+ * this information available.
+ * Information about name of the OpenSafSmfExecControl is read from the
+ * openSafSmfExecControl attribute in the OpenSafSmfConfig IMM object.
+ * This handler will create and use a copy of the OpenSafSmfExecControl object.
+ * The reason for this is that changes affecting the OpenSafSmfExecControl or
+ * the openSafSmfExecControl attribute in the OpenSafSmfConfig IMM object shall
+ * not affect an ongoing campaign.
+ * This copy will be created when the install() method is called.
+ * To cleanup the uninstall() method shall be used. This will delete the copy
+ * of the OpenSafSmfExecControl object.
+ * If a campaign shall continue after a SI-swap or reboot this 
SmfExecControlHdl
+ * object has to be created again but the install() method shall not be used.
+ * The other method can be used as long as the OpenSafSmfExecControl copy still
+ * exist.
+ */
+class SmfExecControlObjHandler {
+ public:
+
+  SmfExecControlObjHandler();
+  ~SmfExecControlObjHandler();
+
+  /**
+   * Setup the exec control handling
+   *
+   * @return true if success
+   */
+  bool install();
+
+  /**
+   * Cleanup the exec control handling and remove the exec control object copy
+   * Note:
+   * This is also done in the destructor except removal of the exec control
+   * object copy. However, if this is not done there is no resource leek since
+   * an existing copy will be overwritten.
+   */
+  void uninstall();
+
+  
+  /* Return corresponding values
+   * The errinfo parameter will be given a value true if success or false
+   * if fail
+   */
+  SaUint32T procExecMode(bool *errinfo);
+  SaUint32T numberOfSingleSteps(bool *errinfo);
+  std::vector <std::string> nodesForSingleStep(bool *errinfo);
+  bool smfProtectExecControlDuringInit(bool *errinfo);
+
+
+ private:
+  // NOTE: Info about private methods can be found in .cc file
+
+  bool getValuesFromImmCopy();
+  bool readExecControlObject(const char* exec_ctrl_name);
+  bool readOpenSafSmfConfig();
+  bool copyExecControlObject();
+  void removeExecControlObjectCopy();
+  bool createAllImmHandles();
+  void saveAttributeDescriptors();
+
+
+  // For OpenSafSmfExecControl object data
+  SmfImmUtils *p_immutil_object;
+  const char* c_class_name = "OpenSafSmfExecControl";
+  const char* c_openSafSmfExecControl = "";
+  SaUint32T m_smfProtectExecControlDuringInit;
+  bool m_smfProtectExecControlDuringInit_valid;
+  SaUint32T m_procExecMode;
+  bool m_procExecMode_valid;
+  SaUint32T m_numberOfSingleSteps;
+  bool m_numberOfSingleSteps_valid;
+  std::vector <std::string> m_nodesForSingleStep;
+  bool m_nodesForSingleStep_valid;
+
+  
+  // For OpenSafSmfExecControl object copy
+  const char* c_openSafSmfExecControl_copy = "openSafSmfExecControl_copy";
+  SaImmAttrValuesT_2 **m_attributes;
+  SaImmAttrValuesT_2 *m_exec_ctrl_name_ad;
+  SaImmAttrValuesT_2 *m_procExecMode_ad;
+  SaImmAttrValuesT_2 *m_numberOfSingleSteps_ad;
+  SaImmAttrValuesT_2 *m_nodesForSingleStep_ad;
+
+
+  // For storing IMM handles
+  const SaVersionT m_immVersion {'A', 2, 1};
+  SaImmHandleT m_omHandle {0};
+  SaImmAdminOwnerHandleT m_ownerHandle {0};
+  SaImmCcbHandleT m_ccbHandle {0};
+  SaImmAccessorHandleT m_accessorHandle {0};
+
+
+  DELETE_COPY_AND_MOVE_OPERATORS(SmfExecControlObjHandler);
+};
+
+#endif /* SMFEXECCONTROLHDL_H */
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
@@ -36,6 +36,7 @@
 #include "SmfRollback.hh"
 #include "SmfUtils.hh"
 #include "smfd.h"
+#include "SmfExecControl.h"
 
 /* ========================================================================
  *   DEFINITIONS
@@ -241,8 +242,9 @@ SmfProcStateInitial::executeInit(SmfUpgr
 {
        TRACE_ENTER();
        LOG_NO("PROC: Start procedure init actions");
-        if 
(SmfCampaignThread::instance()->campaign()->getUpgradeCampaign()->getProcExecutionMode()
 
-           == SMF_MERGE_TO_SINGLE_STEP) {
+        auto camp = SmfCampaignThread::instance()->campaign();
+        int procExecMode = camp->getUpgradeCampaign()->getProcExecutionMode();
+        if (procExecMode == 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());
@@ -250,6 +252,26 @@ SmfProcStateInitial::executeInit(SmfUpgr
                         TRACE_LEAVE();
                         return SMF_PROC_FAILED;
                 }
+        } else if (procExecMode == SMF_BALANCED_MODE) {
+                if (i_proc->getBalancedGroup().empty()) {
+                        TRACE("SmfProcStateInitial::executeInit, Calculate 
steps for original procedure");
+                        if (!i_proc->calculateSteps()) {
+                                LOG_NO("SmfProcStateExecuting::Step 
calculation failed");
+                                return SMF_PROC_FAILED;
+                        }
+                        // Some steps will be merged, mark them as completed
+                        execctrl::allStepsMerged(i_proc);
+                        execctrl::trace("after procStateInit allStepsMerged");
+                } else {
+                        LOG_NO("SmfProcStateInitial::executeInit, create step 
for balanced procedure");
+                        if (!execctrl::createStepForBalancedProc(i_proc)) {
+                                changeState(i_proc, 
SmfProcStateExecFailed::instance());
+                                LOG_NO("SmfProcStateExecuting::executeInit: 
failed to create balanced steps");
+                                TRACE_LEAVE();
+                                return SMF_PROC_FAILED;
+                        }
+                        execctrl::trace("after procStateInit 
createStepsForBalancedProc");
+                }
         } else {
                 TRACE("SmfProcStateInitial::executeInit, Calculate steps");
                 if( !i_proc->calculateSteps() ) {
@@ -351,10 +373,12 @@ SmfProcStateExecuting::executeStep(SmfUp
        std::vector < SmfUpgradeStep * >::const_iterator iter;
         const std::vector < SmfUpgradeStep * >& procSteps = 
i_proc->getProcSteps();
         unsigned int execStepNo = procSteps.size();
+        TRACE("total -execStepNo %d", execStepNo);
 
         for (iter = procSteps.begin(); iter != procSteps.end(); iter++) {
                 SmfStepResultT stepResult;
                 execStepNo--;
+                TRACE("-execStepNo %d, dn: %s", execStepNo, 
(*iter)->getDn().c_str());
 
                 /* Try executing the step */
                 stepResult = (*iter)->execute();
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,10 +73,9 @@ class SmfUpgradeProcedure;
     m_waitToCommit(0),
     m_waitToAllowNewCampaign(0),
     m_noOfExecutingProc(0),
-    m_noOfProcResponses(0),
-    m_procExecutionMode(0)
+    m_noOfProcResponses(0)
 {
-
+        m_execControlHdl = new SmfExecControlObjHandler();
 }
 
 // 
------------------------------------------------------------------------------
@@ -84,22 +83,37 @@ class SmfUpgradeProcedure;
 // 
------------------------------------------------------------------------------
 SmfUpgradeCampaign::~SmfUpgradeCampaign()
 {
-       TRACE_ENTER();
+        TRACE_ENTER();
         //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) &&
+        int procexec = getProcExecutionMode();
+        if ((procexec == SMF_MERGE_TO_SINGLE_STEP || procexec == 
SMF_BALANCED_MODE) &&
            (m_state->getState() != SA_SMF_CMPG_INITIAL)) {
-                delete(m_mergedProcedure);
+                for (auto& it: m_procedure) {
+                        delete it;
+                }
+                m_procedure.clear();
+        } 
+        for (auto& it: m_originalProcedures) {
+                delete it;
         }
+        m_originalProcedures.clear();
 
-       std::vector < SmfUpgradeProcedure * >::iterator iter;
+        delete m_execControlHdl;
 
-       for (iter = m_procedure.begin(); iter != m_procedure.end(); ++iter) {
-               delete(*iter);
-       }
+        TRACE_LEAVE();
+}
 
-       TRACE_LEAVE();
+// 
------------------------------------------------------------------------------
+// addMergedProcedure()
+// 
------------------------------------------------------------------------------
+void SmfUpgradeCampaign::addMergedProcedure(SmfUpgradeProcedure* procedure) {
+        if (m_originalProcedures.size() == 0) {
+                m_originalProcedures = m_procedure;
+                m_procedure.clear();
+        }
+        m_procedure.push_back(procedure);
 }
 
 // 
------------------------------------------------------------------------------
@@ -1016,9 +1030,6 @@ SmfUpgradeCampaign::continueExec()
             currentState = m_state->getState();
         }
 
-       //Read and set the ProcExecutionMode after cluster reboot
-       setProcExecutionMode(smfd_cb->procExecutionMode);
-
         //Start procedure threads
         if (SmfCampaignThread::instance()->campaign()->startProcedureThreads() 
!= SA_AIS_OK) {
                 LOG_NO("continueExec() fail to restart procedure threads");
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
@@ -28,6 +28,7 @@
 #include "SmfCampaignInit.hh"
 #include "SmfCampaignWrapup.hh"
 #include "SmfCampaignThread.hh"
+#include "SmfExecControlHdl.h"
 
 class SmfUpgradeProcedure;
 class SmfCampState;
@@ -400,35 +401,27 @@ void verify();
         SaAisErrorT checkSmfRestartIndicator();
 
 ///
-/// Purpose: get procedure list
-/// @param   None.
-/// @return  list of procedures.
+/// Purpose: Get the unmodified procedures, no merged procedures included
 ///
-       const std::vector < SmfUpgradeProcedure * >& getProcedures() { return 
m_procedure; }
+       const std::vector<SmfUpgradeProcedure*>& getOriginalProcedures() { 
return m_originalProcedures; };
 
-/// Purpose: set the merged procedure
-/// @param   A SmfUpgradeProcedure *
-/// @return  the procedure.
 ///
-       void setMergedProc(SmfUpgradeProcedure * proc) { m_mergedProcedure = 
proc; }
+/// Purpose: Add the merged procedure while saving the original
+///
+       void addMergedProcedure(SmfUpgradeProcedure* procedure);
 
-/// Purpose: get the merged procedure
-/// @param   None.
-/// @return  the procedure.
 ///
-       SmfUpgradeProcedure * getMergedProc() { return m_mergedProcedure; }
+/// Purpose: Can be used with any procedure execution mode
+///
+       const std::vector<SmfUpgradeProcedure*>& getProcedures() { return 
m_procedure; }
 
-/// Purpose: Set the procedure ecxecution mode
-/// @param   The execution mode.
-/// @return  none
-///
-       void setProcExecutionMode(int i_procExecutionMode) { 
m_procExecutionMode = i_procExecutionMode; }
+        SmfExecControlObjHandler* getExecControlHdl() { return 
m_execControlHdl; }
 
 /// Purpose: Get the procedure ecxecution mode
 /// @param   none
 /// @return  The execution mode.
 ///
-       int getProcExecutionMode() { return m_procExecutionMode; }
+        SaUint32T getProcExecutionMode() { return 
m_execControlHdl->procExecMode(NULL); }
 
        SmfCampaignInit & getCampaignInit() { return  m_campInit; }
        SmfCampaignWrapup & getCampaignWrapup() { return  m_campWrapup; }
@@ -482,12 +475,12 @@ private:
         std::string m_configurationBase;
        SmfCampaignInit m_campInit;
        SmfCampaignWrapup m_campWrapup;
-        std::vector < SmfUpgradeProcedure * >m_procedure;
-        SmfUpgradeProcedure * m_mergedProcedure;
+        std::vector<SmfUpgradeProcedure*> m_procedure;
+        std::vector<SmfUpgradeProcedure*> m_originalProcedures;
         SaTimeT m_waitToCommit;
         SaTimeT m_waitToAllowNewCampaign;
        int m_noOfExecutingProc;
         int m_noOfProcResponses;
-       int m_procExecutionMode;
+        SmfExecControlObjHandler* m_execControlHdl;
 };
 #endif                         // __SMFUPGRADECAMPAIGN_H
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
@@ -51,6 +51,7 @@
 #include "SmfUpgradeAction.hh"
 #include "SmfUtils.hh"
 #include "smfd.h"
+#include "SmfExecControl.h"
 
 // This static member variable is the object counter for upgrade procedures
 unsigned long SmfUpgradeProcedure::s_procCounter = 1;
@@ -146,6 +147,14 @@ SmfUpgradeProcedure::~SmfUpgradeProcedur
                         delete(*stepit);
                 }
         }
+        //} else {
+        //        unsigned int execMode = 
SmfCampaignThread::instance()->campaign()->getUpgradeCampaign()->getProcExecutionMode();
+        //        if (execMode == SMF_BALANCED_MODE) {
+        //                for (auto& step : m_procSteps) {
+        //                        delete step;
+        //                }
+        //        }
+        //}
 
        TRACE_LEAVE();
 }
@@ -1171,7 +1180,7 @@ SmfUpgradeProcedure::mergeStepIntoSingle
         std::list < unitNameAndState > forAddRemoveDU;
        std::list < unitNameAndState > tmpDU;
         SmfUpgradeCampaign * camp = 
SmfCampaignThread::instance()->campaign()->getUpgradeCampaign();
-        const std::vector < SmfUpgradeProcedure * >& procedures = 
camp->getProcedures();
+        const std::vector < SmfUpgradeProcedure * >& procedures = 
camp->getOriginalProcedures();
         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());
@@ -2775,12 +2784,16 @@ SmfUpgradeProcedure::getImmSteps()
                return SA_AIS_ERR_NOT_EXIST;
        }
 
+        unsigned int execMode = 
SmfCampaignThread::instance()->campaign()->getUpgradeCampaign()->getProcExecutionMode();
        if (upgradeMethod->getUpgradeMethod() == SA_SMF_ROLLING) {
-               TRACE("Rolling upgrade");
-               rc = getImmStepsRolling();
+                TRACE("Rolling upgrade");
+                rc = getImmStepsRolling();
+                if (execMode == SMF_BALANCED_MODE) {
+                        // We get here after a SI SWAP, some steps will be 
merged, mark them as completed
+                        execctrl::allStepsMerged(this);
+                }
        } else if (upgradeMethod->getUpgradeMethod() == SA_SMF_SINGLE_STEP) {
-                if 
(SmfCampaignThread::instance()->campaign()->getUpgradeCampaign()->getProcExecutionMode()
-                   == SMF_MERGE_TO_SINGLE_STEP) {  //This is a merged single 
step
+                if (execMode == 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
@@ -3140,7 +3153,7 @@ SmfUpgradeProcedure::getImmStepsMergedSi
                int initActionId = 1;
                int wrapupActionId = 1;
                SmfUpgradeCampaign * camp = 
SmfCampaignThread::instance()->campaign()->getUpgradeCampaign();
-               const std::vector < SmfUpgradeProcedure * >& procedures = 
camp->getProcedures();
+               const std::vector < SmfUpgradeProcedure * >& procedures = 
camp->getOriginalProcedures();
                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]",
@@ -3415,7 +3428,7 @@ SmfUpgradeProcedure::bundleRefFromSsCamp
        //----------------------------------------------------------------
        //Read all the bundles to add/remove from the parsed camaign
         SmfUpgradeCampaign * camp = 
SmfCampaignThread::instance()->campaign()->getUpgradeCampaign();
-       const std::vector < SmfUpgradeProcedure * >& procedures = 
camp->getProcedures();
+       const std::vector < SmfUpgradeProcedure * >& procedures = 
camp->getOriginalProcedures();
        std::vector < SmfUpgradeProcedure * >::const_iterator proc_iter;
        std::list < SmfBundleRef > bundlesOldProcSS;
        std::list < SmfBundleRef *> bundlesOldProcRO;
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
@@ -551,7 +551,7 @@ class SmfUpgradeProcedure {
 /// @param    -
 /// @return   The list of upgrade steps.
 ///
-        const std::vector < SmfUpgradeStep * >& getProcSteps() { return 
m_procSteps; }
+        std::vector < SmfUpgradeStep * >& getProcSteps() { return m_procSteps; 
}
 
 ///
 /// Purpose:  Add the list of upgrade steps
@@ -717,8 +717,6 @@ class SmfUpgradeProcedure {
        friend class SmfProcState;
        friend class SmfCampStateSuspendingExec;
 
- private:
-
 ///
 /// Purpose:  Get iformation from AMF config in IMM about Components, SUs and 
nodes needed for upgrade 
 /// @param    A reference to a std::multimap<std::string, objectInst>
@@ -727,6 +725,19 @@ class SmfUpgradeProcedure {
        bool getImmComponentInfo(std::multimap<std::string, objectInst> 
&i_objects);
 
 ///
+/// Purpose: When merging with SMF_BALANCED_MODE we need to keep track of 
which balanced group procedures belong to.
+///
+        const std::vector<std::string>& getBalancedGroup() { return 
m_balancedGroup; }
+
+///
+/// Purpose: When merging with SMF_BALANCED_MODE we need to keep track of 
which balanced group procedures belong to.
+///
+        void setBalancedGroup(std::vector<std::string> group) { 
m_balancedGroup = group; }
+
+ private:
+
+
+///
 /// Purpose:  Change the procedure stste. If i_onlyInternalState == false, the 
IMM procedure object is updated and 
 ///           a state change event is sent
 /// @param    -
@@ -765,6 +776,7 @@ class SmfUpgradeProcedure {
         std::list < SmfCallback * >m_afterUnlock;   //Container of the 
procedure callbacks to be invoked onstep, ataction
        sem_t m_semaphore;
         bool m_isMergedProcedure;
+        std::vector<std::string> m_balancedGroup;
 };
 
 //////////////////////////////////////////////////
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
@@ -57,6 +57,10 @@
 #include "smfd.h"
 #include "osaf_time.h"
 
+#if 0 /*LLDTEST*/
+#include "SmfExecControlHdl.h"
+#endif
+
 /* ========================================================================
  *   DEFINITIONS
  * ========================================================================
@@ -678,6 +682,51 @@ SmfUpgradeStep::lockDeactivationUnits()
        SmfAdminOperation units(&m_deactivationUnit.m_actedOn);
        bool rc = units.lock();
 
+#if 0
+       /*LLDTEST*/
+       bool errinfo = true;
+       SmfExecControlObjHandler *lldtest_p = new SmfExecControlObjHandler;
+       lldtest_p->install();
+       TRACE("LLDTEST 1 %s: procExecMode=%d", __FUNCTION__,
+               lldtest_p->procExecMode(errinfo));
+       TRACE("LLDTEST 1 %s: numberOfSingleSteps=%d", __FUNCTION__,
+               lldtest_p->numberOfSingleSteps(errinfo));
+       TRACE("LLDTEST 1 %s: errinfo = %s", __FUNCTION__,
+               lldtest_p? "true": "false");
+
+       //nodesForSingleStep
+       std::vector <std::string> tst_nodes;
+       tst_nodes = lldtest_p->nodesForSingleStep(errinfo);
+
+       for(auto& tst_node : tst_nodes ) {
+               TRACE("LLDTEST 1 %s: nodesForSingleStep='%s'", __FUNCTION__,
+                tst_node.c_str());
+       }
+
+        // Check what happens if we remove the exec control object copy!
+        //lldtest_p->uninstall();
+
+        delete lldtest_p;
+
+
+        /* Try to create an object again and read attributes */
+        SmfExecControlObjHandler lldtest;
+       TRACE("LLDTEST 2 %s: procExecMode=%d", __FUNCTION__,
+               lldtest.procExecMode(errinfo));
+       TRACE("LLDTEST 2 %s: numberOfSingleSteps=%d", __FUNCTION__,
+               lldtest.numberOfSingleSteps(errinfo));
+       TRACE("LLDTEST 2 %s: errinfo = %s", __FUNCTION__,
+               errinfo? "true": "false");
+
+       //nodesForSingleStep
+       tst_nodes = lldtest.nodesForSingleStep(errinfo);
+
+       for(auto& tst_node : tst_nodes ) {
+               TRACE("LLDTEST 2 %s: nodesForSingleStep='%s'", __FUNCTION__,
+                tst_node.c_str());
+       }
+#endif
+
        return rc;
 }
 
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
@@ -707,6 +707,12 @@ class SmfUpgradeStep {
 /// @return   true on success else false
 ///
        bool readSmfClusterControllers();
+///
+/// Purpose:  Set step state
+/// @param    The state
+/// @return   None
+///
+       void setStepState(SaSmfStepStateT i_state);
 
         friend class SmfStepState;
 
@@ -761,13 +767,6 @@ class SmfUpgradeStep {
        void setImmStateAndSendNotification(SaSmfStepStateT i_state);
 
 ///
-/// Purpose:  Set step state
-/// @param    The state
-/// @return   None
-///
-       void setStepState(SaSmfStepStateT i_state);
-
-///
 /// Purpose: Disables copy constructor
 ///
         SmfUpgradeStep(const SmfUpgradeStep &);
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
@@ -60,7 +60,7 @@ extern "C" {
 /* SMF execution modes */
 #define SMF_STANDARD_MODE 0
 #define SMF_MERGE_TO_SINGLE_STEP 1
-#define SMF_MERGE_TO_NODE_ROLLING 2
+#define SMF_BALANCED_MODE 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
@@ -886,32 +886,6 @@ 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
@@ -1152,11 +1126,6 @@ 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);
@@ -1177,7 +1146,6 @@ 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;
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
@@ -70,11 +70,6 @@ typedef struct smfd_cb {
        pthread_mutex_t lock;                     /* Used by smfd_cb_t 
lock/unlock functions */
        pthread_mutex_t imm_lock;                 /* Used when IMM OI handle is 
shared between campaign thread and main thread*/
        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;
 

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

Reply via email to