Object delete is added
The ccbdemo1 command has changed name to ccbdemo_create
A new command ccbdemo_delete is added
A new command ccbdemo_modify is also added but is still dummy. This is in
preparation for adding object modify

Also some cleanup and some bug fixes
---
 src/smf/Makefile.am                                |  95 ++++++++--
 src/smf/smfd/imm_modify_config/README              |  13 +-
 .../{creator.cc => add_operation_to_ccb.cc}        | 102 +++++++++--
 .../{creator.h => add_operation_to_ccb.h}          |  26 ++-
 src/smf/smfd/imm_modify_config/immccb.cc           | 188 ++++++++++++++++----
 src/smf/smfd/imm_modify_config/immccb.h            |  18 +-
 src/smf/smfd/imm_modify_demo/Makefile              |   2 +-
 .../{ccbdemo1.cc => ccbdemo_create.cc}             |  25 +--
 src/smf/smfd/imm_modify_demo/ccbdemo_delete.cc     | 173 +++++++++++++++++++
 src/smf/smfd/imm_modify_demo/ccbdemo_modify.cc     | 191 +++++++++++++++++++++
 10 files changed, 748 insertions(+), 85 deletions(-)
 rename src/smf/smfd/imm_modify_config/{creator.cc => add_operation_to_ccb.cc} 
(50%)
 rename src/smf/smfd/imm_modify_config/{creator.h => add_operation_to_ccb.h} 
(53%)
 rename src/smf/smfd/imm_modify_demo/{ccbdemo1.cc => ccbdemo_create.cc} (96%)
 create mode 100644 src/smf/smfd/imm_modify_demo/ccbdemo_delete.cc
 create mode 100644 src/smf/smfd/imm_modify_demo/ccbdemo_modify.cc

diff --git a/src/smf/Makefile.am b/src/smf/Makefile.am
index 05b35c0aa..673387db6 100644
--- a/src/smf/Makefile.am
+++ b/src/smf/Makefile.am
@@ -115,7 +115,7 @@ noinst_HEADERS += \
 # IMM configuration modifier
 noinst_HEADERS += \
        src/smf/smfd/imm_modify_config/attribute.h \
-       src/smf/smfd/imm_modify_config/creator.h \
+       src/smf/smfd/imm_modify_config/add_operation_to_ccb.h \
        src/smf/smfd/imm_modify_config/immccb.h
 
 # IMM OM C++ APIs
@@ -205,7 +205,7 @@ bin_osafsmfd_SOURCES = \
 # IMM configuration modifier
 bin_osafsmfd_SOURCES += \
        src/smf/smfd/imm_modify_config/attribute.cc \
-       src/smf/smfd/imm_modify_config/creator.cc \
+       src/smf/smfd/imm_modify_config/add_operation_to_ccb.cc \
        src/smf/smfd/imm_modify_config/immccb.cc
 
 # IMM OM C++ APIs
@@ -258,29 +258,100 @@ endif
 # Demos and test
 if ENABLE_TESTS
 
-bin_PROGRAMS += bin/ccbdemo1
+bin_PROGRAMS += bin/ccbdemo_create bin/ccbdemo_delete bin/ccbdemo_modify
+
 dist_pkgimmxml_svc_DATA += \
        src/smf/smfd/imm_modify_demo/democlass.xml
 
-#noinst_HEADERS +=
+# DEMO Create
+# -----------
+bin_ccbdemo_create_CFLAGS = $(AM_CFLAGS) -Wformat=1
+
+bin_ccbdemo_create_CPPFLAGS = \
+       -DSA_EXTENDED_NAME_SOURCE \
+       $(AM_CPPFLAGS)
+
+bin_ccbdemo_create_SOURCES = \
+       src/smf/smfd/imm_modify_demo/ccbdemo_create.cc
+
+# IMM configuration modifier
+bin_ccbdemo_create_SOURCES += \
+       src/smf/smfd/imm_modify_config/attribute.cc \
+       src/smf/smfd/imm_modify_config/add_operation_to_ccb.cc \
+       src/smf/smfd/imm_modify_config/immccb.cc
+
+# IMM OM C++ APIs
+bin_ccbdemo_create_SOURCES += \
+       src/smf/smfd/imm_om_api/common/common.cc \
+       src/smf/smfd/imm_om_api/common/imm_attribute.cc \
+       src/smf/smfd/imm_om_api/om_admin_owner_clear.cc \
+       src/smf/smfd/imm_om_api/om_admin_owner_handle.cc \
+       src/smf/smfd/imm_om_api/om_admin_owner_set.cc \
+       src/smf/smfd/imm_om_api/om_ccb_handle.cc \
+       src/smf/smfd/imm_om_api/om_ccb_object_create.cc \
+       src/smf/smfd/imm_om_api/om_ccb_object_delete.cc \
+       src/smf/smfd/imm_om_api/om_ccb_object_modify.cc \
+       src/smf/smfd/imm_om_api/om_handle.cc
+
+bin_ccbdemo_create_LDADD = \
+       lib/libosaf_common.la \
+       lib/libSaImmOm.la \
+       lib/libopensaf_core.la
+
+# DEMO Delete
+# -----------
+bin_ccbdemo_delete_CFLAGS = $(AM_CFLAGS) -Wformat=1
+
+bin_ccbdemo_delete_CPPFLAGS = \
+       -DSA_EXTENDED_NAME_SOURCE \
+       $(AM_CPPFLAGS)
+
+bin_ccbdemo_delete_SOURCES = \
+       src/smf/smfd/imm_modify_demo/ccbdemo_delete.cc
+
+# IMM configuration modifier
+bin_ccbdemo_delete_SOURCES += \
+       src/smf/smfd/imm_modify_config/attribute.cc \
+       src/smf/smfd/imm_modify_config/add_operation_to_ccb.cc \
+       src/smf/smfd/imm_modify_config/immccb.cc
+
+# IMM OM C++ APIs
+bin_ccbdemo_delete_SOURCES += \
+       src/smf/smfd/imm_om_api/common/common.cc \
+       src/smf/smfd/imm_om_api/common/imm_attribute.cc \
+       src/smf/smfd/imm_om_api/om_admin_owner_clear.cc \
+       src/smf/smfd/imm_om_api/om_admin_owner_handle.cc \
+       src/smf/smfd/imm_om_api/om_admin_owner_set.cc \
+       src/smf/smfd/imm_om_api/om_ccb_handle.cc \
+       src/smf/smfd/imm_om_api/om_ccb_object_create.cc \
+       src/smf/smfd/imm_om_api/om_ccb_object_delete.cc \
+       src/smf/smfd/imm_om_api/om_ccb_object_modify.cc \
+       src/smf/smfd/imm_om_api/om_handle.cc
+
+bin_ccbdemo_delete_LDADD = \
+       lib/libosaf_common.la \
+       lib/libSaImmOm.la \
+       lib/libopensaf_core.la
 
-bin_ccbdemo1_CFLAGS = $(AM_CFLAGS) -Wformat=1
+# DEMO Modify
+# -----------
+bin_ccbdemo_modify_CFLAGS = $(AM_CFLAGS) -Wformat=1
 
-bin_ccbdemo1_CPPFLAGS = \
+bin_ccbdemo_modify_CPPFLAGS = \
        -DSA_EXTENDED_NAME_SOURCE \
        $(AM_CPPFLAGS)
 
-bin_ccbdemo1_SOURCES = \
-       src/smf/smfd/imm_modify_demo/ccbdemo1.cc
+bin_ccbdemo_modify_SOURCES = \
+       src/smf/smfd/imm_modify_demo/ccbdemo_modify.cc
 
 # IMM configuration modifier
-bin_ccbdemo1_SOURCES += \
+bin_ccbdemo_modify_SOURCES += \
        src/smf/smfd/imm_modify_config/attribute.cc \
-       src/smf/smfd/imm_modify_config/creator.cc \
+       src/smf/smfd/imm_modify_config/add_operation_to_ccb.cc \
        src/smf/smfd/imm_modify_config/immccb.cc
 
 # IMM OM C++ APIs
-bin_ccbdemo1_SOURCES += \
+bin_ccbdemo_modify_SOURCES += \
        src/smf/smfd/imm_om_api/common/common.cc \
        src/smf/smfd/imm_om_api/common/imm_attribute.cc \
        src/smf/smfd/imm_om_api/om_admin_owner_clear.cc \
@@ -292,7 +363,7 @@ bin_ccbdemo1_SOURCES += \
        src/smf/smfd/imm_om_api/om_ccb_object_modify.cc \
        src/smf/smfd/imm_om_api/om_handle.cc
 
-bin_ccbdemo1_LDADD = \
+bin_ccbdemo_modify_LDADD = \
        lib/libosaf_common.la \
        lib/libSaImmOm.la \
        lib/libopensaf_core.la
diff --git a/src/smf/smfd/imm_modify_config/README 
b/src/smf/smfd/imm_modify_config/README
index 9d7e04817..a0d9750b4 100644
--- a/src/smf/smfd/imm_modify_config/README
+++ b/src/smf/smfd/imm_modify_config/README
@@ -95,10 +95,10 @@ Output:  None. We have taken ownership of one or several 
objects.
          of the object(s) will fail with EXIST
 
 6.
-Add a modification to the CCB. Based on a valid CCB handle (5.)
-Possible modification operations are:
+Add a CCB operation. Based on a valid CCB handle (5.)
+Possible operations are:
     Create an object. We have to be owner of the parent
-    Delete an object. We have to be owner of the parent
+    Delete an object. We have to be owner of the object and its subtree
     Modify the value of one or more attributes in one object. We have to be
     owner of the object.
 Recovery:  BAD HANDLE; Start from (1.)
@@ -107,8 +107,8 @@ Recovery:  BAD HANDLE; Start from (1.)
                              It is possible to distinguish between resource and
                              and validate error by using the
                              saImmOmCcbGetErrorStrings() API
-           BUSY; An admin operation is ongoing on an object to be deleted
-                 We can try again (6.)
+           BUSY; An admin operation is ongoing on an object to be deleted or
+                 modified. We can try again (6.)
 
 6a.
 Set admin ownership for all objects to be created and/or modified with
@@ -124,3 +124,6 @@ Apply the CCB. Based on a valid CCB handle
 Recovery:  BAD HANDLE; Start from (1.)
            FAILED OPERATION; If Resource error start from (1.) else
                              if validate error, Fail.
+                             It is possible to distinguish between resource and
+                             and validate error by using the
+                             saImmOmCcbGetErrorStrings() API
diff --git a/src/smf/smfd/imm_modify_config/creator.cc 
b/src/smf/smfd/imm_modify_config/add_operation_to_ccb.cc
similarity index 50%
rename from src/smf/smfd/imm_modify_config/creator.cc
rename to src/smf/smfd/imm_modify_config/add_operation_to_ccb.cc
index 975f6002b..9db1ab1c5 100644
--- a/src/smf/smfd/imm_modify_config/creator.cc
+++ b/src/smf/smfd/imm_modify_config/add_operation_to_ccb.cc
@@ -16,7 +16,7 @@
  *
  */
 
-#include "creator.h"
+#include "add_operation_to_ccb.h"
 
 #if 1 // TODO(Lennart) Remove
 #include <stdio.h>
@@ -39,20 +39,28 @@
 
 #include "smf/smfd/imm_om_api/common/common.h"
 #include "smf/smfd/imm_om_api/om_ccb_object_create.h"
+#include "smf/smfd/imm_om_api/om_ccb_object_delete.h"
 #include "smf/smfd/imm_om_api/om_ccb_object_modify.h"
 #include "attribute.h"
 
+bool IsResorceAbort(const SaImmCcbHandleT& ccbHandle) {
+  bool rc = false;
 
-// Add one create operation to a CCB
-// Recovery:  BAD HANDLE; kRestartOm
-//            FAILED OPERATION; kRestartOm
-//              The CCB has been aborted because of an OI problem
-//            OK;   kContinue
-//            Other AIS return codes; kFail
-// return: Recovery information.
-//         See immccb.h
-
-int AddObjectCreateToCcbf(const SaImmCcbHandleT& ccb_handle,
+  const SaStringT *errString = nullptr;
+  SaAisErrorT ais_rc = saImmOmCcbGetErrorStrings(ccbHandle, &errString);
+  if ((ais_rc == SA_AIS_OK) && (errString != nullptr)) {
+    TRACE("%s: Error string: '%s'", __FUNCTION__, errString[0]);
+    std::string err_str(errString[0]);
+    if (err_str.find("IMM: Resource abort: ") != std::string::npos) {
+      // Is Resource Abort
+      rc = true;
+    }
+  }
+
+  return rc;
+}
+
+int AddObjectCreateToCcb(const SaImmCcbHandleT& ccb_handle,
                        const modelmodify::CreateDescriptor& create_descriptor) 
{
   TRACE_ENTER2("LLDTEST1: Parent '%s', Class '%s'",
                create_descriptor.parent_name.c_str(),
@@ -86,11 +94,20 @@ int AddObjectCreateToCcbf(const SaImmCcbHandleT& ccb_handle,
     if (creator.AddObjectCreateToCcb() == false) {
       // Add create Fail
       SaAisErrorT ais_rc = creator.ais_error();
-      if ((ais_rc == SA_AIS_ERR_BAD_HANDLE) ||
-          (ais_rc == SA_AIS_ERR_FAILED_OPERATION)) {
+      if (ais_rc == SA_AIS_ERR_BAD_HANDLE) {
         recovery_info = modelmodify::kRestartOm;
         TRACE("LLDTEST1 %s: AddObjectCreateToCcb(), %s, kRestartOm",
               __FUNCTION__, saf_error(ais_rc));
+      } else if (ais_rc == SA_AIS_ERR_FAILED_OPERATION) {
+        if (IsResorceAbort(ccb_handle)) {
+          TRACE("LLDTEST1 %s: AddObjectCreateToCcb(), %s, kRestartOm",
+                __FUNCTION__, saf_error(ais_rc));
+          recovery_info = modelmodify::kRestartOm;
+        } else {
+          LOG_NO("LLDTEST1 %s: AddObjectCreateToCcb() Fail, %s", __FUNCTION__,
+                 saf_error(ais_rc));
+          recovery_info = modelmodify::kFail;
+        }
       } else {
         // Unrecoverable Fail
         LOG_NO("LLDTEST1 %s: ObjectCreateCcbAdd(), %s, kFail",
@@ -107,3 +124,62 @@ int AddObjectCreateToCcbf(const SaImmCcbHandleT& 
ccb_handle,
                modelmodify::RecoveryTxt(recovery_info));
   return recovery_info;
 }
+
+// Add one delete operation to a CCB
+// Recovery:  BAD HANDLE; kRestartOm
+//            FAILED OPERATION; kRestartOm or kFail
+//            BUSY; An admin operation is ongoing on an object to be deleted
+//                  We can try again to add the create
+// return: Recovery information. See immccb.h
+int AddObjectDeleteToCcb(const SaImmCcbHandleT& ccb_handle,
+                         const modelmodify::DeleteDescriptor&
+                         delete_descriptor) {
+
+  int recovery_info = modelmodify::kNotSet;
+
+  // Setup an object deleter
+  immom::ImmOmCcbObjectDelete deletor(ccb_handle);
+
+  // Add the delete operation to the CCB. Try again if BUSY
+  base::Timer busy_timer(modelmodify::kBusyTimeout);
+  while (busy_timer.is_timeout() != true) {
+    if (deletor.AddObjectDeleteToCcb(delete_descriptor.object_name) == false) {
+      // Add delete Fail
+      SaAisErrorT ais_rc = deletor.ais_error();
+      if (ais_rc == SA_AIS_ERR_BUSY) {
+        base::Sleep(base::MillisToTimespec(modelmodify::kBusyWait));
+        continue;
+      } else if (ais_rc == SA_AIS_ERR_BAD_HANDLE) {
+        TRACE("LLDTEST1 %s: AddObjectDeleteToCcb() Recover, %s", __FUNCTION__,
+              saf_error(ais_rc));
+        recovery_info = modelmodify::kRestartOm;
+        break;
+      } else if (SA_AIS_ERR_FAILED_OPERATION) {
+        if (IsResorceAbort(ccb_handle)) {
+          TRACE("LLDTEST1 %s: AddObjectDeleteToCcb(), %s, kRestartOm",
+                __FUNCTION__, saf_error(ais_rc));
+          recovery_info = modelmodify::kRestartOm;
+          break;
+        } else {
+          // Unrecoverable Fail
+          LOG_NO("LLDTEST1 %s: AddObjectDeleteToCcb() Fail, %s", __FUNCTION__,
+                 saf_error(ais_rc));
+          recovery_info = modelmodify::kFail;
+          break;
+        }
+      }
+    }
+
+    // AddObjectDeleteToCcb() Success
+    recovery_info = modelmodify::kContinue;
+    break;
+  }
+  if ((busy_timer.is_timeout() == true) &&
+      (recovery_info == modelmodify::kNotSet)) {
+    LOG_NO("LLDTEST %s: AddObjectDeleteToCcb() Fail, BUSY timeout",
+           __FUNCTION__);
+    recovery_info = modelmodify::kFail;
+  }
+
+  return recovery_info;
+}
diff --git a/src/smf/smfd/imm_modify_config/creator.h 
b/src/smf/smfd/imm_modify_config/add_operation_to_ccb.h
similarity index 53%
rename from src/smf/smfd/imm_modify_config/creator.h
rename to src/smf/smfd/imm_modify_config/add_operation_to_ccb.h
index 855464989..73a5e2d13 100644
--- a/src/smf/smfd/imm_modify_config/creator.h
+++ b/src/smf/smfd/imm_modify_config/add_operation_to_ccb.h
@@ -31,14 +31,34 @@
 #ifndef IMM_API_H
 #define IMM_API_H
 
+// Check if the reason for SA_AIS_ERR_FAILED_OPERATION is a "resorce abort"
+// Can be used immediately after an add operation or an apply operation has
+// returned SA_AIS_ERR_FAILED_OPERATION
+// Note:  SA_AIS_ERR_FAILED_OPERATION can be returned for two reasons:
+//        1.  Validation error.
+//            This is a Fail. Cannot be recovered
+//        2.  Resource abort.
+bool IsResorceAbort(const SaImmCcbHandleT& ccbHandle);
+
 // Add one create operation to a CCB
 // Recovery:  BAD HANDLE; kRestartOm
-//            FAILED OPERATION; kRestartOm
+//            FAILED OPERATION; kRestartOm or kFail
+//            BUSY; An admin operation is ongoing on an object to be deleted
+//                  We can try again to add the create
+// return: Recovery information. See immccb.h
+int AddObjectCreateToCcb(const SaImmCcbHandleT& ccb_handle,
+                         const modelmodify::CreateDescriptor&
+                         create_descriptor);
+
+// Add one delete operation to a CCB
+// Recovery:  BAD HANDLE; kRestartOm
+//            FAILED OPERATION; kRestartOm or kFail
 //            BUSY; An admin operation is ongoing on an object to be deleted
 //                  We can try again to add the create
 // return: Recovery information. See immccb.h
-int AddObjectCreateToCcbf(const SaImmCcbHandleT& ccb_handle,
-                       const modelmodify::CreateDescriptor& create);
+int AddObjectDeleteToCcb(const SaImmCcbHandleT& ccb_handle,
+                         const modelmodify::DeleteDescriptor&
+                         delete_descriptor);
 
 
 #endif /* IMM_API_H */
diff --git a/src/smf/smfd/imm_modify_config/immccb.cc 
b/src/smf/smfd/imm_modify_config/immccb.cc
index 5ea897508..9524aecb8 100644
--- a/src/smf/smfd/imm_modify_config/immccb.cc
+++ b/src/smf/smfd/imm_modify_config/immccb.cc
@@ -40,7 +40,7 @@
 #include "base/time.h"
 #include "base/saf_error.h"
 
-#include "creator.h"
+#include "add_operation_to_ccb.h"
 
 #include "smf/smfd/imm_om_api/common/common.h"
 #include "smf/smfd/imm_om_api/om_admin_owner_clear.h"
@@ -117,9 +117,18 @@ bool ObjectModification::DoModification(CcbDescriptor 
modifications) {
       continue;
     }
 
+    // TODO(Lennart)
     // AddModifications. Request modifications of exiting IMM objects
 
     // AddDeletes. Delete IMM objects
+    recovery_info = AddDeletes(modifications.delete_descriptors);
+    if (recovery_info == kFail) {
+      LOG_NO("LLDTEST %s: AddDeletes() Fail", __FUNCTION__);
+      break;
+    } else if (recovery_info == kRestartOm) {
+      TRACE("LLDTEST %s: AddDeletes() Restart", __FUNCTION__);
+      continue;
+    }
 
     // Apply the IMM CCB
     recovery_info = ApplyModifications();
@@ -325,25 +334,25 @@ void ObjectModification::FinalizeHandles() {
 // Return:  Recovery information. See Private constants
 int ObjectModification::AdminOwnerSet(std::vector<std::string>& objects,
                                       SaImmScopeT scope) {
-  TRACE_ENTER2("LLDTEST");
+  TRACE_ENTER2("LLDTEST2");
 
   if (imm_ao_owner_set_ == nullptr) {
     // Should never happen
-    LOG_ER("LLDTEST %s: No admin owner set handler is created", __FUNCTION__);
+    LOG_ER("LLDTEST2 %s: No admin owner set handler is created", __FUNCTION__);
     return kFail;
   }
 
   if (objects.empty()) {
     // Should never happen
-    LOG_ER("LLDTEST %s: No objects", __FUNCTION__);
+    LOG_ER("LLDTEST2 %s: No objects", __FUNCTION__);
     return kFail;
   }
 
   // Set objects to become admin owner of
-  TRACE("LLDTEST %s: Becoming admin owner of the following objects:",
+  TRACE("LLDTEST2 %s: Becoming admin owner of the following objects:",
         __FUNCTION__);
   for (auto& object : objects) {
-    TRACE("LLDTEST %s: Object '%s'", __FUNCTION__, object.c_str());
+    TRACE("LLDTEST2 %s: Object '%s'", __FUNCTION__, object.c_str());
     if (object.empty()) {
       // Do not add empty strings (IMM root)
       continue;
@@ -355,9 +364,7 @@ int 
ObjectModification::AdminOwnerSet(std::vector<std::string>& objects,
   // An object is a cluster global resource. We cannot become admin owner if
   // the object is already owned by someone else. Wait a reasonable time for 
the
   // resource to be released
-  const uint64_t exist_timeout = 30000; // 30 sec
-  const uint64_t exist_wait = 2000; // 2 sec
-  base::Timer exist_timer(exist_timeout);
+  base::Timer exist_timer(kExistTimeout);
   SaAisErrorT ais_rc = SA_AIS_OK;
   int recovery_info = kNotSet;
 
@@ -366,15 +373,15 @@ int 
ObjectModification::AdminOwnerSet(std::vector<std::string>& objects,
       ais_rc = imm_ao_owner_set_->ais_error();
       if (ais_rc == SA_AIS_ERR_EXIST) {
         // Another owner of object(s) exist. Wait for other owner release
-        TRACE("LLDTEST %s: Waiting for SA_AIS_ERR_EXIST", __FUNCTION__);
-        base::Sleep(base::MillisToTimespec(exist_wait));
+        TRACE("LLDTEST2 %s: Waiting for SA_AIS_ERR_EXIST", __FUNCTION__);
+        base::Sleep(base::MillisToTimespec(kExistWait));
         continue;
       } else if (ais_rc == SA_AIS_ERR_BAD_HANDLE) {
-        TRACE("LLDTEST %s: SetAdminOwner() Restart", __FUNCTION__);
+        TRACE("LLDTEST2 %s: SetAdminOwner() Restart", __FUNCTION__);
         recovery_info = kRestartOm;
         break;
       } else {
-        LOG_NO("LLDTEST %s: SetAdminOwner() Fail, %s", __FUNCTION__,
+        LOG_NO("LLDTEST2 %s: SetAdminOwner() Fail, %s", __FUNCTION__,
                saf_error(ais_rc));
         recovery_info = kFail;
         break;
@@ -385,26 +392,36 @@ int 
ObjectModification::AdminOwnerSet(std::vector<std::string>& objects,
     break;
   }
   if ((exist_timer.is_timeout() == true) && (recovery_info == kNotSet)) {
-    LOG_NO("LLDTEST %s: SetAdminOwner() Fail, exist timeout",
+    LOG_NO("LLDTEST2 %s: SetAdminOwner() Fail, EXIST timeout",
            __FUNCTION__);
     recovery_info = kFail;
   }
 
-  TRACE_LEAVE2("LLDTEST");
+  TRACE_LEAVE2("LLDTEST2");
   return recovery_info;
 }
 
+#if 0 // TODO(Lennart) Not used so it can be removed
 // Release admin ownership that was previously set using AdminOwnerSet(...)
 // Recovery:  BAD_HANDLE; Nothing to do. In this case admin ownership is
 //                        released
 //            BUSY;       An admin operation is ongoing on one of the objects
 //                        belonging to this admin owner. We can try again
 int ObjectModification::AdminOwnerRelease(void) {
-  TRACE_ENTER2("LLDTEST");
+  TRACE_ENTER2("LLDTEST21");
+
+  // TODO(Lennart) Remove this function. It is never needed. The admin owner
+  // shall not be released until the CCB is applied. The admin owner will be
+  // released when the om handle is finalized (note that the
+  // releaseOwnershipOnFinalize flag must be set to true. This is done by
+  // default when the admin owner is created)
+  // For now this function is dummy
+  return kContinue;
+
 
   if (imm_ao_owner_set_ == nullptr) {
     // Should never happen
-    LOG_ER("LLDTEST %s: No admin owner handle is created", __FUNCTION__);
+    LOG_ER("LLDTEST21 %s: No admin owner handle is created", __FUNCTION__);
     return kFail;
   }
 
@@ -414,9 +431,7 @@ int ObjectModification::AdminOwnerRelease(void) {
   // used. Wait a reasonable time for the resource to be released.
   // Note:  This should in practice not be possible in this context since this
   //        admin owner is "owned" and used by this class only
-  const uint64_t busy_timeout = 30000; // 30 sec
-  const uint64_t busy_wait = 2000; // 2 sec
-  base::Timer busy_timer(busy_timeout);
+  base::Timer busy_timer(kBusyTimeout);
   SaAisErrorT ais_rc = SA_AIS_OK;
   int recovery_info = kNotSet;
 
@@ -428,11 +443,11 @@ int ObjectModification::AdminOwnerRelease(void) {
         recovery_info = kContinue;
         break;
       } else if (ais_rc == SA_AIS_ERR_BUSY) {
-        TRACE("LLDTEST %s: SA_AIS_ERR_BUSY", __FUNCTION__);
-        base::Sleep(base::MillisToTimespec(busy_wait));
+        TRACE("LLDTEST21 %s: SA_AIS_ERR_BUSY", __FUNCTION__);
+        base::Sleep(base::MillisToTimespec(kBusyWait));
         continue;
       } else {
-        LOG_NO("LLDTEST %s: ReleaseAdminOwner() Fail, %s", __FUNCTION__,
+        LOG_NO("LLDTEST21 %s: ReleaseAdminOwner() Fail, %s", __FUNCTION__,
                saf_error(ais_rc));
         recovery_info = kFail;
         break;
@@ -443,16 +458,16 @@ int ObjectModification::AdminOwnerRelease(void) {
     break;
   }
   if ((busy_timer.is_timeout() == true) && (recovery_info == kNotSet)) {
-    LOG_NO("LLDTEST %s: ReleaseAdminOwner() Fail, busy timeout",
+    LOG_NO("LLDTEST21 %s: ReleaseAdminOwner() Fail, BUSY timeout",
            __FUNCTION__);
     recovery_info = kFail;
   }
 
   imm_ao_owner_set_->ClearObjectNames();
-  TRACE_LEAVE2("LLDTEST");
+  TRACE_LEAVE2("LLDTEST21");
   return recovery_info;
 }
-
+#endif
 
 // Add create requests for all objects to be created
 // Set admin ownership for parent to all objects to be created with scope
@@ -464,8 +479,6 @@ int ObjectModification::AdminOwnerRelease(void) {
 //        this is not needed to check
 // Recovery:  BAD HANDLE; Restart CCB handling
 //            FAILED OPERATION; Restart CCB handling
-//            NOT_EXIST; Restart CCB handling. The OI may be temporarily
-//                       unavailable
 // Return:  Recovery information
 int ObjectModification::AddCreates(std::vector<CreateDescriptor>&
       create_descriptors) {
@@ -475,11 +488,11 @@ int 
ObjectModification::AddCreates(std::vector<CreateDescriptor>&
   // Do this for all create descriptors
   for (auto& create_descriptor : create_descriptors) {
     if (create_descriptor.parent_name.empty() == false) {
-      // Become admin owner of parent if there is a parent. I no parent the
+      // Become admin owner of parent if there is a parent. If no parent the
       // IMM object will be created as a root object
       std::vector<std::string> imm_objects;
       imm_objects.push_back(create_descriptor.parent_name);
-      int recovery_info = AdminOwnerSet(imm_objects, SA_IMM_ONE);
+      recovery_info = AdminOwnerSet(imm_objects, SA_IMM_ONE);
       if (recovery_info == kFail) {
         LOG_NO("LLDTEST %s: AdminOwnerSet() Fail", __FUNCTION__);
         break;
@@ -492,10 +505,12 @@ int 
ObjectModification::AddCreates(std::vector<CreateDescriptor>&
     // Add the object create request to the ccb:
     recovery_info = AddCreate(create_descriptor);
     if (recovery_info != kContinue) {
-      LOG_NO("LLDTEST %s: AddCreate() Recovery Info %s",
+      TRACE("LLDTEST %s: AddCreate() Recovery Info %s",
              __FUNCTION__, RecoveryTxt(recovery_info));
     }
 
+#if 0 // TODO(Lennart) Shall be done after CCB Apply and is done when
+      // OM Finalize is done so this code can be removed
     // Cleanup admin ownership
     // We shall always try to do this if an admin owner was set
     int release_recovery_info = AdminOwnerRelease();
@@ -513,6 +528,7 @@ int 
ObjectModification::AddCreates(std::vector<CreateDescriptor>&
       TRACE("LLDTEST %s: AdminOwnerRelease() Restart", __FUNCTION__);
       break;
     }
+#endif
   } // For all create descriptors
 
   if (recovery_info == kNotSet) {
@@ -533,12 +549,104 @@ int ObjectModification::AddCreate(CreateDescriptor& 
create_descriptor) {
   int recovery_info = kNotSet;
   SaImmCcbHandleT ccb_handle = imm_ccb_handle_->GetHandle();
 
-  recovery_info = AddObjectCreateToCcbf(ccb_handle, create_descriptor);
+  recovery_info = AddObjectCreateToCcb(ccb_handle, create_descriptor);
 
   TRACE_LEAVE2("LLDTEST");
   return recovery_info;
 }
 
+// Add delete requests for all objects to be deleted
+// Set admin ownership for objects to be deleted with scope SA_IMM_SUBTREE.
+// Add all delete operations to the CCB
+// Note1: We have to be owner of the object and the sub tree
+// Note2: It is not a problem to set admin ownership of an object that already
+//        has an admin owner if the same admin owner name is used, meaning that
+//        this is not needed to check
+// Recovery:  BAD HANDLE; Restart CCB handling
+//            FAILED OPERATION; Restart CCB handling if resource abort
+// Return:  Recovery information
+int ObjectModification::AddDeletes(std::vector<DeleteDescriptor>&
+      delete_descriptors) {
+  TRACE_ENTER2("LLDTEST");
+  int recovery_info = kNotSet;
+
+  // Do this for all delete descriptors
+  for (auto& delete_descriptor : delete_descriptors) {
+    if (delete_descriptor.object_name.empty() == false) {
+      // Become admin owner of object if there is an object. If not Fail
+      std::vector<std::string> imm_objects;
+      imm_objects.push_back(delete_descriptor.object_name);
+      recovery_info = AdminOwnerSet(imm_objects, SA_IMM_SUBTREE);
+      if (recovery_info == kFail) {
+        LOG_NO("LLDTEST %s: AdminOwnerSet() Fail", __FUNCTION__);
+        break;
+      } else if (recovery_info == kRestartOm) {
+        TRACE("LLDTEST %s: AdminOwnerSet() Restart", __FUNCTION__);
+        break;
+      }
+    } else {
+      LOG_NO("LLDTEST %s: AddDeletes() Fail, No object to delete",
+             __FUNCTION__);
+      recovery_info = kFail;
+    }
+
+    // Add the object delete request to the ccb:
+    recovery_info = AddDelete(delete_descriptor);
+    if (recovery_info != kContinue) {
+      TRACE("LLDTEST %s: AddDelete() Recovery Info %s",
+             __FUNCTION__, RecoveryTxt(recovery_info));
+    }
+
+#if 0 // TODO(Lennart) Shall be done after CCB Apply and is done when
+      // OM Finalize is done so this code can be removed
+    // Cleanup admin ownership
+    // Cleanup admin ownership
+    // We shall always try to do this if an admin owner was set
+    int release_recovery_info = AdminOwnerRelease();
+    if (recovery_info != kContinue) {
+      // If the previous AddDelete was not successful then recovery info from
+      // AdminOwnerRelease is not relevant. We must break based on AddDelete
+      // recovery info.
+      break;
+    }
+
+    if (release_recovery_info == kFail) {
+      LOG_NO("LLDTEST %s: AdminOwnerRelease() Fail", __FUNCTION__);
+      break;
+    } else if (release_recovery_info == kRestartOm) {
+      TRACE("LLDTEST %s: AdminOwnerRelease() Restart", __FUNCTION__);
+      break;
+    }
+#endif
+  } // For all delete descriptors
+
+   if (recovery_info == kNotSet) {
+    // All deletes are added, no recovery needed
+    recovery_info = kContinue;
+  }
+  TRACE_LEAVE2("LLDTEST, recovery_info = %s", RecoveryTxt(recovery_info));
+  return recovery_info;
+}
+
+// Add one delete descriptor to the ccb
+//  Set object name
+//  Add the delete request to the ccb
+// Return: Recovery information
+int ObjectModification::AddDelete(DeleteDescriptor& delete_descriptor) {
+  TRACE_ENTER2("LLDTEST");
+  int recovery_info = kNotSet;
+  SaImmCcbHandleT ccb_handle = imm_ccb_handle_->GetHandle();
+
+  recovery_info = AddObjectDeleteToCcb(ccb_handle, delete_descriptor);
+
+
+  TRACE_LEAVE2("LLDTEST");
+  return recovery_info;
+}
+
+
+
+
 // Apply the CCB. Based on a valid CCB handle
 // Recovery:  BAD HANDLE; Restart CCBhandling
 //            FAILED OPERATION; Restart CCBhandling
@@ -548,12 +656,22 @@ int ObjectModification::ApplyModifications() {
 
   if (imm_ccb_handle_->ApplyCcb() == false) {
     SaAisErrorT ais_rc = imm_ccb_handle_->ais_error();
-    if ((ais_rc == SA_AIS_ERR_BAD_HANDLE) ||
-        (ais_rc == SA_AIS_ERR_FAILED_OPERATION)) {
+    if (ais_rc == SA_AIS_ERR_BAD_HANDLE) {
       TRACE("LLDTEST %s: ApplyCcb() Restart %s", __FUNCTION__,
             saf_error(ais_rc));
       recovery_info = kRestartOm;
-    } else {
+    } else if (ais_rc == SA_AIS_ERR_FAILED_OPERATION) {
+        if (IsResorceAbort(imm_ccb_handle_->GetHandle())) {
+          TRACE("LLDTEST %s: ApplyCcb() Restart %s", __FUNCTION__,
+                saf_error(ais_rc));
+          recovery_info = modelmodify::kRestartOm;
+        } else {
+          LOG_NO("LLDTEST %s: ApplyCcb() Fail %s", __FUNCTION__,
+                 saf_error(ais_rc));
+          recovery_info = modelmodify::kFail;
+        }
+    }
+    else {
       LOG_ER("LLDTEST %s: ApplyCcb() Fail", __FUNCTION__);
       recovery_info = kFail;
     }
diff --git a/src/smf/smfd/imm_modify_config/immccb.h 
b/src/smf/smfd/imm_modify_config/immccb.h
index f7ffbc3d8..e633fd1bc 100644
--- a/src/smf/smfd/imm_modify_config/immccb.h
+++ b/src/smf/smfd/imm_modify_config/immccb.h
@@ -264,6 +264,14 @@ const int kRestartOm = 2;
 // Fail, no recovery possible
 const int kFail = 3;
 
+// Internal timeout and wait time for BUSY return from IMM
+const uint64_t kBusyTimeout = 30000; // 30 sec
+const uint64_t kBusyWait = 2000; // 2 sec
+// Internal timeout and wait time for EXIST return from IMM
+const uint64_t kExistTimeout = 30000; // 30 sec
+const uint64_t kExistWait = 2000; // 2 sec
+
+// Recovery code to text
 inline static const char* RecoveryTxt(int recovery_info) {
   switch (recovery_info) {
     case modelmodify::kContinue:
@@ -348,11 +356,14 @@ class ObjectModification {
   int CreateCcb(void);
 
   int AdminOwnerSet(std::vector<std::string>& objects, SaImmScopeT scope);
-  int AdminOwnerRelease(void);
+  //int AdminOwnerRelease(void);
 
   // Handle om_ccb_object_create()
   int AddCreates(std::vector<CreateDescriptor>& create_descriptors);
   int AddCreate(CreateDescriptor& create_descriptor);
+  // Handle om_ccb_object_delete()
+  int AddDeletes(std::vector<DeleteDescriptor>& delete_descriptors);
+  int AddDelete(DeleteDescriptor& delete_descriptor);
 
   int ApplyModifications(void);
 
@@ -407,23 +418,18 @@ static inline std::string SaNametToString(SaNameT* 
name_value) {
 }
 
 static inline std::string SaAnytToString(SaAnyT* anyt_value) {
-  std::cout << __FUNCTION__ << " >>" << std::endl;
   std::string out_string;
   if ((anyt_value->bufferSize == 0) || (anyt_value->bufferAddr == nullptr)) {
     out_string = "";
-    std::cout << "  No data. Empty string created" << std::endl;
   } else {
     SaSizeT anyt_size = anyt_value->bufferSize;
-    std::cout << "  bufferSize = " << anyt_size << std::endl;
     SaUint8T* anyt_buffer = anyt_value->bufferAddr;
     printf("  bufferAddr = %p\n", anyt_buffer);
     for (SaSizeT i = 0; i < anyt_size; i++) {
-      //printf("  buffer[%lld] = 0x%x\n", i, *anyt_buffer);
       out_string.push_back(static_cast<char>(*anyt_buffer++));
     }
   }
 
-  std::cout << __FUNCTION__ << " <<" << std::endl;
   return out_string;
 }
 
diff --git a/src/smf/smfd/imm_modify_demo/Makefile 
b/src/smf/smfd/imm_modify_demo/Makefile
index a67423aee..9492d3272 100644
--- a/src/smf/smfd/imm_modify_demo/Makefile
+++ b/src/smf/smfd/imm_modify_demo/Makefile
@@ -15,5 +15,5 @@
 #
 
 all:
-       $(MAKE) -C ../../../.. bin/ccbdemo1
+       $(MAKE) -C ../../../.. bin/ccbdemo_create bin/ccbdemo_delete 
bin/ccbdemo_modify
 
diff --git a/src/smf/smfd/imm_modify_demo/ccbdemo1.cc 
b/src/smf/smfd/imm_modify_demo/ccbdemo_create.cc
similarity index 96%
rename from src/smf/smfd/imm_modify_demo/ccbdemo1.cc
rename to src/smf/smfd/imm_modify_demo/ccbdemo_create.cc
index bea650975..124abe9eb 100644
--- a/src/smf/smfd/imm_modify_demo/ccbdemo1.cc
+++ b/src/smf/smfd/imm_modify_demo/ccbdemo_create.cc
@@ -27,6 +27,7 @@
 #include "ais/include/saImm.h"
 #include "ais/include/saAis.h"
 #include "base/osaf_extended_name.h"
+#include "osaf/configmake.h"
 
 #include "smf/smfd/imm_modify_config/immccb.h"
 
@@ -91,6 +92,7 @@ void PrintName(SaNameT* name) {
 #if 0 // LLDTEST Working code using om API directly
 int main() {
   cout << "Creating an object using 'immom' directly" << endl;
+  cout << "Class: ImmTestValuesConfig" << endl;
   cout << "Creating: TestObj1=1,safApp=safSmfService" << endl << endl;
 
   // Prepare extended name
@@ -214,21 +216,24 @@ int main() {
   cout << "ApplyCcb()" << endl;
   if (ccb_handle.ApplyCcb() == false) {
     cout << "ApplyCcb() Fail" << endl;
-    return -1;
+    //return -1;
   }
 
+  cout << "Clean up; Finalize OM handle" << endl;
+  om_handle.FinalizeHandle();
+
   return 0;
 }
 #endif
 
 #if 1 // Using modelmofify immccb
 int main(void) {
-  cout << "I am ccbdemo1 creating an object using 'modelmodify'" << std::endl;
+  cout << "I am ccbdemo1 creating 2 objects using 'modelmodify'" << endl;
   cout << "Class name: ImmTestValuesConfig" << endl;
   cout << "Creating: TestObj1=1,safApp=safSmfService" << endl;
-  cout << "Creating: TestObj2=1,safApp=safSmfService" << endl << endl;
+  cout << "Creating root object: TestObj2=1" << endl << endl;
 
-#if 0// Enable trace
+#if 1// Enable trace
   unsigned int category_mask = 0xffffffff;
   const char* logPath = PKGLOGDIR "/osafccbdemo1";
   if (logtrace_init("ccbdemo1", logPath, category_mask) == -1) {
@@ -245,7 +250,7 @@ int main(void) {
   setenv("SA_ENABLE_EXTENDED_NAMES", "1", 1);
   osaf_extended_name_init();
   // Note: Long DN must be configured in IMM configuration object before
-  // running ccbdemo1
+  // running ccbdemo_...
   // DN for that object is opensafImm=opensafImm,safApp=safImmService
 
 
@@ -418,16 +423,16 @@ int main(void) {
   test_ccb.AddCreate(test_object_create2);
 
   cout << "CCB descriptor for test_ccb created" << endl;
-  PrintCcbDescriptor(test_ccb);
+  //PrintCcbDescriptor(test_ccb);
   cout << endl;
 
-  modelmodify::ObjectModification obj_creator;
-  obj_creator.SetCcbFlags(0);
-  if (obj_creator.DoModification(test_ccb) == false) {
+  modelmodify::ObjectModification model_modifier;
+  model_modifier.SetCcbFlags(0);
+  if (model_modifier.DoModification(test_ccb) == false) {
     cout << "DoModification() Fail" << endl;
   }
 
-  cout << endl << "ccbdemo1 Done" << endl;
+  cout << endl << "ccbdemo_create Done" << endl;
   return 0;
 }
 #endif
diff --git a/src/smf/smfd/imm_modify_demo/ccbdemo_delete.cc 
b/src/smf/smfd/imm_modify_demo/ccbdemo_delete.cc
new file mode 100644
index 000000000..534433194
--- /dev/null
+++ b/src/smf/smfd/imm_modify_demo/ccbdemo_delete.cc
@@ -0,0 +1,173 @@
+/*      -*- OpenSAF  -*-
+ *
+ * (C) Copyright 2008 The OpenSAF Foundation
+ * Copyright Ericsson AB 2017 - All Rights Reserved.
+ *
+ * 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 <limits.h>
+
+#include <string>
+#include <vector>
+#include <memory>
+#include <utility>
+#include <iostream>
+
+#include "ais/include/saImm.h"
+#include "ais/include/saAis.h"
+#include "base/osaf_extended_name.h"
+#include "osaf/configmake.h"
+
+#include "smf/smfd/imm_modify_config/immccb.h"
+
+#if 1 // Low level OM interface
+#include "smf/smfd/imm_om_api/common/common.h"
+#include "smf/smfd/imm_om_api/om_admin_owner_clear.h"
+#include "smf/smfd/imm_om_api/om_admin_owner_handle.h"
+#include "smf/smfd/imm_om_api/om_admin_owner_set.h"
+#include "smf/smfd/imm_om_api/om_ccb_handle.h"
+#include "smf/smfd/imm_om_api/om_ccb_object_create.h"
+#include "smf/smfd/imm_om_api/om_ccb_object_delete.h"
+#include "smf/smfd/imm_om_api/om_ccb_object_modify.h"
+#include "smf/smfd/imm_om_api/om_handle.h"
+#endif
+
+using namespace std;
+
+#if 0 // LLDTEST Working code using om API directly
+// Note: Before running this code an object to delete must have been created
+//       This can be done by running ccbdemo_create
+int main() {
+  cout << "Deleting an object using 'immom' directly. Object must exist" <<
+      endl;
+  cout << "Class: ImmTestValuesConfig" << endl;
+  cout << "Delete: TestObj1=1,safApp=safSmfService" << endl << endl;
+
+  // Prepare extended name
+  setenv("SA_ENABLE_EXTENDED_NAMES", "1", 1);
+  osaf_extended_name_init();
+
+  immom::ImmOmHandle om_handle;
+  if (om_handle.InitializeHandle() == false) {
+    cout << "OM handle Fail" << endl;
+    return -1;
+  }
+
+  immom::ImmOmAdminOwnerHandle ao_handle(om_handle.GetHandle(), "ccbdemo1");
+  if (ao_handle.InitializeHandle() == false) {
+    cout << "AO handle Fail" << endl;
+    return -1;
+  }
+
+  immom::ImmOmCcbHandle ccb_handle(ao_handle.GetHandle(), 0);
+  if (ccb_handle.InitializeHandle() == false) {
+    cout << "CCB handle Fail" << endl;
+    return -1;
+  }
+
+  cout << "Become AO of the object and sub tree to be deleted" << endl;
+  immom::ImmOmAdminOwnerSet ao_setter(ao_handle.GetHandle());
+  ao_setter.AddObjectName("TestObj1=1,safApp=safSmfService"); // Object
+  if (ao_setter.SetAdminOwner(SA_IMM_SUBTREE) == false) {
+    cout << "AO Set Fail, " << ao_setter.ais_error_string() << endl;
+    return -1;
+  }
+
+  cout << "Add delete operation to CCB" << endl;
+  immom::ImmOmCcbObjectDelete deleter(ccb_handle.GetHandle());
+  if (deleter.AddObjectDeleteToCcb("TestObj1=1,safApp=safSmfService")
+                                   == false) {
+    cout << "AddObjectDeleteToCcb() Fail, " << deleter.ais_error_string()
+         << endl;
+  }
+
+#if 0 // Don't do this
+  cout << "Release AO using ao_setter release method" << endl;
+  if (ao_setter.ReleaseAdminOwner() == false) {
+    cout << "AO release Fail, " << ao_setter.ais_error_string() << endl;
+    //return -1;
+  }
+#endif
+
+  cout << "ApplyCcb()" << endl;
+  if (ccb_handle.ApplyCcb() == false) {
+    cout << "ApplyCcb() Fail" << endl;
+    return -1;
+  }
+
+#if 0 // Don't do this
+  cout << "Release AO using ao_setter release method" << endl;
+  if (ao_setter.ReleaseAdminOwner() == false) {
+    cout << "AO release Fail, " << ao_setter.ais_error_string() << endl;
+    //return -1;
+  }
+#endif
+
+  cout << "Clean up; Finalize OM handle" << endl;
+  om_handle.FinalizeHandle();
+
+  return 0;
+}
+#endif
+
+#if 1 // LLDTEST: Using modelmodify to delete an object
+int main() {
+  cout << "Deleting 2 objects using 'modelmodify'" << endl;
+  cout << "Delete: TestObj1=1,safApp=safSmfService" << endl;
+  cout << "Delete root object: TestObj1=2" << endl << endl;
+
+#if 1// Enable trace
+  unsigned int category_mask = 0xffffffff;
+  const char* logPath = PKGLOGDIR "/osafccbdemo1";
+  if (logtrace_init("ccbdemo1", logPath, category_mask) == -1) {
+    syslog(LOG_ERR, "osafntfimcnd logtrace_init FAILED");
+    /* We allow to execute anyway. */
+    cout << "logtrace_init() Fail" << endl;
+  } else {
+    //cout << "logtrace enabled" << endl;
+  }
+#endif
+
+#if 0
+  // Prepare/enable extended name
+  // ----------------------------
+  setenv("SA_ENABLE_EXTENDED_NAMES", "1", 1);
+  osaf_extended_name_init();
+  // Note: Long DN must be configured in IMM configuration object before
+  // running ccbdemo_...
+  // DN for that object is opensafImm=opensafImm,safApp=safImmService
+#endif
+
+  modelmodify::CcbDescriptor test_ccb;
+  modelmodify::DeleteDescriptor delete_object;
+
+  delete_object.object_name = "TestObj1=1,safApp=safSmfService";
+  test_ccb.AddDelete(delete_object);
+
+  // Here we test to reuse the Delete Descriptor and to delete a root object
+  delete_object.object_name = "TestObj2=1";
+  test_ccb.AddDelete(delete_object);
+
+  modelmodify::ObjectModification model_modifier;
+  model_modifier.SetCcbFlags(0); // No OI for this class/objects of this class
+  if (model_modifier.DoModification(test_ccb) == false) {
+    cout << "DoModification() Fail" << endl;
+  }
+
+  cout << endl << "ccbdemo_delete Done" << endl;
+
+  return 0;
+}
+
+#endif
\ No newline at end of file
diff --git a/src/smf/smfd/imm_modify_demo/ccbdemo_modify.cc 
b/src/smf/smfd/imm_modify_demo/ccbdemo_modify.cc
new file mode 100644
index 000000000..399267052
--- /dev/null
+++ b/src/smf/smfd/imm_modify_demo/ccbdemo_modify.cc
@@ -0,0 +1,191 @@
+/*      -*- OpenSAF  -*-
+ *
+ * (C) Copyright 2008 The OpenSAF Foundation
+ * Copyright Ericsson AB 2017 - All Rights Reserved.
+ *
+ * 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 <limits.h>
+
+#include <string>
+#include <vector>
+#include <memory>
+#include <utility>
+#include <iostream>
+
+#include "ais/include/saImm.h"
+#include "ais/include/saAis.h"
+#include "base/osaf_extended_name.h"
+#include "osaf/configmake.h"
+
+#include "smf/smfd/imm_modify_config/immccb.h"
+
+#if 1 // Low level OM interface
+#include "smf/smfd/imm_om_api/common/common.h"
+#include "smf/smfd/imm_om_api/om_admin_owner_clear.h"
+#include "smf/smfd/imm_om_api/om_admin_owner_handle.h"
+#include "smf/smfd/imm_om_api/om_admin_owner_set.h"
+#include "smf/smfd/imm_om_api/om_ccb_handle.h"
+#include "smf/smfd/imm_om_api/om_ccb_object_create.h"
+#include "smf/smfd/imm_om_api/om_ccb_object_delete.h"
+#include "smf/smfd/imm_om_api/om_ccb_object_modify.h"
+#include "smf/smfd/imm_om_api/om_handle.h"
+#endif
+
+using namespace std;
+
+/*      -*- OpenSAF  -*-
+ *
+ * (C) Copyright 2008 The OpenSAF Foundation
+ * Copyright Ericsson AB 2017 - All Rights Reserved.
+ *
+ * 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 <limits.h>
+
+#include <string>
+#include <vector>
+#include <memory>
+#include <utility>
+#include <iostream>
+
+#include "ais/include/saImm.h"
+#include "ais/include/saAis.h"
+#include "base/osaf_extended_name.h"
+#include "osaf/configmake.h"
+
+#include "smf/smfd/imm_modify_config/immccb.h"
+
+#if 1 // Low level OM interface
+#include "smf/smfd/imm_om_api/common/common.h"
+#include "smf/smfd/imm_om_api/om_admin_owner_clear.h"
+#include "smf/smfd/imm_om_api/om_admin_owner_handle.h"
+#include "smf/smfd/imm_om_api/om_admin_owner_set.h"
+#include "smf/smfd/imm_om_api/om_ccb_handle.h"
+#include "smf/smfd/imm_om_api/om_ccb_object_create.h"
+#include "smf/smfd/imm_om_api/om_ccb_object_delete.h"
+#include "smf/smfd/imm_om_api/om_ccb_object_modify.h"
+#include "smf/smfd/imm_om_api/om_handle.h"
+#endif
+
+using namespace std;
+
+#if 0 // LLDTEST Working code using om API directly
+// Note: Before running this code an object to modify must have been created
+//       This can be done by running ccbdemo_create
+int main() {
+  cout << "Modifying an object using 'immom' directly. Object must exist" <<
+      endl;
+  cout << "Class: ImmTestValuesConfig" << endl;
+  cout << "Modify: TestObj1=1,safApp=safSmfService" << endl << endl;
+
+  // Prepare extended name
+  setenv("SA_ENABLE_EXTENDED_NAMES", "1", 1);
+  osaf_extended_name_init();
+
+  immom::ImmOmHandle om_handle;
+  if (om_handle.InitializeHandle() == false) {
+    cout << "OM handle Fail" << endl;
+    return -1;
+  }
+
+  immom::ImmOmAdminOwnerHandle ao_handle(om_handle.GetHandle(), "ccbdemo1");
+  if (ao_handle.InitializeHandle() == false) {
+    cout << "AO handle Fail" << endl;
+    return -1;
+  }
+
+  immom::ImmOmCcbHandle ccb_handle(ao_handle.GetHandle(), 0);
+  if (ccb_handle.InitializeHandle() == false) {
+    cout << "CCB handle Fail" << endl;
+    return -1;
+  }
+
+  cout << "Become AO of the object to be modified" << endl;
+  immom::ImmOmAdminOwnerSet ao_setter(ao_handle.GetHandle());
+  ao_setter.AddObjectName("TestObj1=1,safApp=safSmfService"); // Object
+  if (ao_setter.SetAdminOwner(SA_IMM_SUBTREE) == false) {
+    cout << "AO Set Fail, " << ao_setter.ais_error_string() << endl;
+    return -1;
+  }
+
+  cout << "Setup modification(s)" << endl;
+
+
+  cout << "Add modify operation(s) to CCB" << endl;
+//  immom::ImmOmCcbObjectDelete deleter(ccb_handle.GetHandle());
+//  if (deleter.AddObjectDeleteToCcb("TestObj1=1,safApp=safSmfService")
+//                                   == false) {
+//    cout << "AddObjectDeleteToCcb() Fail, " << deleter.ais_error_string()
+//         << endl;
+//  }
+  std::string object1 = "TestObj1=1,safApp=safSmfService";
+  //std::string object2 = "TestObj2=1";
+
+  immom::ImmOmCcbObjectModify modifier(ccb_handle.GetHandle(), object1);
+
+  // Add 10 and 20 to existing SaUint32TValues
+//    AddAttributeValue(const std::string& name,
+//                    const std::vector<T*>& list_of_ptr_to_values);
+  std::vector<SaUint32T> uint32_values{10, 20};
+  std::vector<SaUint32T*> uint32_values_pointers;
+  SaUint32T* val_p = uint32_values.data();
+  uint32_values_pointers.push_back(val_p++);
+  uint32_values_pointers.push_back(val_p);
+
+  modifier.AddAttributeValue("SaUint32TValues", uint32_values_pointers);
+  if (modifier.AddObjectModifyToCcb() == false) {
+    cout << "AddObjectModifyToCcb() Fail, " << modifier.ais_error_string()
+         << endl;
+  }
+
+  cout << "ApplyCcb()" << endl;
+  if (ccb_handle.ApplyCcb() == false) {
+    cout << "ApplyCcb() Fail" << endl;
+    return -1;
+  }
+
+#if 0 // Don't do this
+  cout << "Release AO using ao_setter release method" << endl;
+  if (ao_setter.ReleaseAdminOwner() == false) {
+    cout << "AO release Fail, " << ao_setter.ais_error_string() << endl;
+    //return -1;
+  }
+#endif
+
+  cout << "Clean up; Finalize OM handle" << endl;
+  om_handle.FinalizeHandle();
+
+  return 0;
+}
+#endif
+
+#if 1 // Modifying object using modelmodify
+int main() {
+  cout << "ccb_modify" << endl;
+
+  return 0;
+}
+#endif
-- 
2.15.1


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Opensaf-devel mailing list
Opensaf-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to