Ack

Limitations and rules for usage has to be documented but a separate document 
ticket has to be created.

Thanks
Lennart

> -----Original Message-----
> From: Rafael Odzakow
> Sent: den 5 september 2016 09:55
> To: [email protected]; Lennart Lund
> <[email protected]>
> Cc: [email protected]
> Subject: [PATCH 1 of 1] smfd: Merge rolling to singlestep procedures for
> several nodes [#1685]
> 
>  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_SMFEXECCONTR
> OL_H_
> +#define
> OPENSAF_STAGING_OSAF_SERVICES_SAF_SMFSV_SMFD_SMFEXECCONTR
> OL_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_SMFEXECCONTR
> OL_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