]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
objclass-sdk: create SDK for Ceph object classes
authorNeha Ojha <nojha@redhat.com>
Wed, 19 Apr 2017 22:25:21 +0000 (15:25 -0700)
committerNeha Ojha <nojha@redhat.com>
Thu, 27 Apr 2017 20:05:53 +0000 (13:05 -0700)
Creates an installable version of "src/include/rados/objclass.h" that allows
object classes to be built outside of the Ceph tree. cls_sdk is an example
of such an object class.

Signed-off-by: Neha Ojha <nojha@redhat.com>
14 files changed:
ceph.spec.in
debian/control
debian/rados-objclass-dev.install [new file with mode: 0644]
doc/rados/api/index.rst
doc/rados/api/objclass-sdk.rst [new file with mode: 0644]
qa/workunits/cls/test_cls_sdk.sh [new file with mode: 0755]
src/cls/CMakeLists.txt
src/cls/sdk/cls_sdk.cc [new file with mode: 0644]
src/include/CMakeLists.txt
src/include/rados/objclass.h [new file with mode: 0644]
src/objclass/objclass.h
src/test/CMakeLists.txt
src/test/cls_sdk/CMakeLists.txt [new file with mode: 0644]
src/test/cls_sdk/test_cls_sdk.cc [new file with mode: 0644]

index 152dcf8c2ee2ed62c58e0c7c1bc4479cc535332d..cb513e0818975eca381948feadfb4df388275bf8 100644 (file)
@@ -718,6 +718,15 @@ This package contains the Java libraries for the Ceph File System.
 
 %endif
 
+%package -n rados-objclass-devel
+Summary:        RADOS object class development kit
+Group:          Development/Libraries
+License:        LGPL-2.0
+Requires:       librados2-devel = %{epoch}:%{version}-%{release}
+%description -n rados-objclass-devel
+This package contains libraries and headers needed to develop RADOS object
+class plugins.
+
 %if 0%{with selinux}
 
 %package selinux
@@ -1642,6 +1651,11 @@ ln -sf %{_libdir}/librbd.so.1 /usr/lib64/qemu/librbd.so.1
 %{_javadir}/libcephfs-test.jar
 %endif
 
+%files -n rados-objclass-devel
+%defattr(-,root,root,-)
+%dir %{_includedir}/rados
+%{_includedir}/rados/objclass.h
+
 %if 0%{with selinux}
 %files selinux
 %defattr(-,root,root,-)
index 1ae3a8a7662c1c8ee0591dedcf5dd99b54897d0c..183b78fba948eba838a8f230036361f3523fc0d7 100644 (file)
@@ -824,3 +824,11 @@ Section: java
 Depends: libcephfs2 (= ${binary:Version}), ${java:Depends},
          ${misc:Depends}, ${shlibs:Depends}
 Description: Java Native Interface library for CephFS Java bindings
+
+Package: rados-objclass-dev
+Architecture: linux-any
+Section: libdevel
+Depends: librados-dev (= ${binary:Version}) ${misc:Depends}
+Description: RADOS object class development kit.
+ .
+ This package contains development files needed for building RADOS object class plugins.
diff --git a/debian/rados-objclass-dev.install b/debian/rados-objclass-dev.install
new file mode 100644 (file)
index 0000000..ac8f90e
--- /dev/null
@@ -0,0 +1 @@
+usr/include/rados/objclass.h
index 4030e70d9aa9d0c7cfd4c360d0786c03e953c417..cccc153cf1d47caf19fa743c875dfb8df4e43aae 100644 (file)
@@ -18,4 +18,5 @@ Ceph, your own interface to Ceph, etc.).
    Introduction to librados <librados-intro>
    librados (C) <librados>
    librados (C++) <libradospp>
-   librados (Python) <python>
\ No newline at end of file
+   librados (Python) <python>
+   object class <objclass-sdk>
diff --git a/doc/rados/api/objclass-sdk.rst b/doc/rados/api/objclass-sdk.rst
new file mode 100644 (file)
index 0000000..6b1162f
--- /dev/null
@@ -0,0 +1,37 @@
+===========================
+SDK for Ceph Object Classes
+===========================
+
+`Ceph` can be extended by creating shared object classes called `Ceph Object 
+Classes`. The existing framework to build these object classes has dependencies 
+on the internal functionality of `Ceph`, which restricts users to build object 
+classes within the tree. The aim of this project is to create an independent 
+object class interface, which can be used to build object classes outside the 
+`Ceph` tree. This allows us to have two types of object classes, 1) those that 
+have in-tree dependencies and reside in the tree and 2) those that can make use 
+of the `Ceph Object Class SDK framework` and can be built outside of the `Ceph` 
+tree because they do not depend on any internal implementation of `Ceph`. This 
+project decouples object class development from Ceph and encourages creation 
+and distribution of object classes as packages.
+
+In order to demonstrate the use of this framework, we have provided an example 
+called ``cls_sdk``, which is a very simple object class that makes use of the 
+SDK framework. This object class resides in the ``src/cls`` directory. 
+
+Installing objclass.h
+---------------------
+
+The object class interface that enables out-of-tree development of object 
+classes resides in ``src/include/rados/`` and gets installed with `Ceph` 
+installation. After running ``make install``, you should be able to see it 
+in ``<prefix>/include/rados``. ::
+
+        ls /usr/local/include/rados
+
+Using the SDK example
+---------------------
+
+The ``cls_sdk`` object class resides in ``src/cls/sdk/``. This gets built and 
+loaded into Ceph, with the Ceph build process. You can run the 
+``ceph_test_cls_sdk`` unittest, which resides in ``src/test/cls_sdk/``, 
+to test this class.
diff --git a/qa/workunits/cls/test_cls_sdk.sh b/qa/workunits/cls/test_cls_sdk.sh
new file mode 100755 (executable)
index 0000000..f1ccdc3
--- /dev/null
@@ -0,0 +1,5 @@
+#!/bin/sh -e
+
+ceph_test_cls_sdk
+
+exit 0
index 0b916907619f0fa5655d9e530194ad841d3a0e92..1c36c1fd0b5e77a899f1dbdb4464fc371352e8ae 100644 (file)
@@ -3,6 +3,11 @@
 set(cls_dir ${CMAKE_INSTALL_LIBDIR}/rados-classes)
 set(cls_embedded_srcs)
 
+# cls_sdk
+add_library(cls_sdk SHARED sdk/cls_sdk.cc)
+set_target_properties(cls_sdk PROPERTIES VERSION "1.0.0" SOVERSION "1")
+install(TARGETS cls_sdk DESTINATION ${cls_dir})
+
 # cls_hello
 set(cls_hello_srcs hello/cls_hello.cc)
 add_library(cls_hello SHARED ${cls_hello_srcs})
diff --git a/src/cls/sdk/cls_sdk.cc b/src/cls/sdk/cls_sdk.cc
new file mode 100644 (file)
index 0000000..1f907b4
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * This is an example RADOS object class built using only the Ceph SDK interface.
+ */
+#include "include/rados/objclass.h"
+
+CLS_VER(1,0)
+CLS_NAME(sdk)
+
+cls_handle_t h_class;
+cls_method_handle_t h_test_coverage_write;
+cls_method_handle_t h_test_coverage_replay;
+
+/**
+ * test_coverage_write - a "write" method that creates an object
+ *
+ * This method modifies the object by making multiple write calls (write,
+ * setxattr and set_val).
+ */
+static int test_coverage_write(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
+{
+  // create the object
+  int ret = cls_cxx_create(hctx, false);
+  if (ret < 0) {
+    CLS_LOG(0, "ERROR: %s(): cls_cxx_create returned %d", __func__, ret);        
+    return ret;
+  }
+
+  uint64_t size;
+  // get the size of the object
+  ret = cls_cxx_stat(hctx, &size, NULL);
+  if (ret < 0)
+    return ret;
+  
+  std::string c = "test";
+  bufferlist bl;
+  bl.append(c);
+
+  // write to the object
+  ret = cls_cxx_write(hctx, 0, bl.length(), &bl);
+  if (ret < 0)
+    return ret;
+  
+  uint64_t new_size;
+  // get the new size of the object
+  ret = cls_cxx_stat(hctx, &new_size, NULL);
+  if (ret < 0)
+    return ret;
+
+  // make some change to the xattr
+  ret = cls_cxx_setxattr(hctx, "foo", &bl);
+  if (ret < 0)
+    return ret;
+
+  // make some change to the omap
+  ret = cls_cxx_map_set_val(hctx, "foo", &bl);
+  if (ret < 0)
+    return ret;
+
+  return 0;
+}
+
+/**
+ * test_coverage_replay - a "read" method to retrieve previously written data
+ *
+ * This method reads the object by making multiple read calls (read, getxattr 
+ * and get_val). It also removes the object after reading.
+ */
+
+static int test_coverage_replay(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
+{
+  CLS_LOG(0, "reading already written object");
+  uint64_t size;
+  // get the size of the object
+  int ret = cls_cxx_stat(hctx, &size, NULL);
+  if (ret < 0)
+    return ret;
+  
+  bufferlist bl;
+  // read the object entry
+  ret = cls_cxx_read(hctx, 0, size, &bl);
+  if (ret < 0)
+    return ret;
+
+  // if the size is incorrect 
+  if (bl.length() != size)
+    return -EIO;
+  
+  bl.clear();
+
+  // read xattr entry
+  ret = cls_cxx_getxattr(hctx, "foo", &bl);
+  if (ret < 0)
+    return ret;
+
+  // if the size is incorrect
+  if (bl.length() != size)
+    return -EIO;
+  
+  bl.clear();
+
+  // read omap entry
+  ret = cls_cxx_map_get_val(hctx, "foo", &bl);
+  if (ret < 0)
+    return ret;
+
+  // if the size is incorrect
+  if (bl.length() != size)
+    return -EIO;
+
+  // remove the object
+  ret = cls_cxx_remove(hctx);
+  if (ret < 0)
+    return ret;
+  
+  return 0;
+}
+
+void __cls_init()
+{
+  CLS_LOG(0, "loading cls_sdk");
+
+  cls_register("sdk", &h_class);
+
+  cls_register_cxx_method(h_class, "test_coverage_write",
+      CLS_METHOD_RD|CLS_METHOD_WR,
+      test_coverage_write, &h_test_coverage_write);
+  
+  cls_register_cxx_method(h_class, "test_coverage_replay",
+      CLS_METHOD_RD|CLS_METHOD_WR,
+      test_coverage_replay, &h_test_coverage_replay);
+}
index fc9cf7d0178b3fdec3ede26f2359c13030da4cdb..7feffe195a9eb6bfab73b5ec38e60e40cc2e9efb 100644 (file)
@@ -8,6 +8,7 @@ install(FILES rados/librados.h
   memory.h
   page.h
   crc32c.h
+  rados/objclass.h
   DESTINATION include/rados)
 install(FILES
   radosstriper/libradosstriper.h
diff --git a/src/include/rados/objclass.h b/src/include/rados/objclass.h
new file mode 100644 (file)
index 0000000..08c5086
--- /dev/null
@@ -0,0 +1,181 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#ifndef CEPH_OBJCLASS_OBJCLASS_PUBLIC_H
+#define CEPH_OBJCLASS_OBJCLASS_PUBLIC_H
+
+#ifdef __cplusplus
+
+#include "buffer.h"
+
+extern "C" {
+#endif
+
+#ifndef BUILDING_FOR_EMBEDDED
+#define CLS_VER(maj,min) \
+int __cls_ver__## maj ## _ ##min = 0; \
+int __cls_ver_maj = maj; \
+int __cls_ver_min = min;
+
+#define CLS_NAME(name) \
+int __cls_name__## name = 0; \
+const char *__cls_name = #name;
+#define CLS_INIT(name) \
+void CEPH_CLS_API __cls_init()
+#else
+#define CLS_VER(maj,min)
+#define CLS_NAME(name)
+#define CLS_INIT(name) \
+void CEPH_CLS_API name##_cls_init()
+#endif
+
+#define CLS_METHOD_RD       0x1 /// method executes read operations
+#define CLS_METHOD_WR       0x2 /// method executes write operations
+#define CLS_METHOD_PROMOTE  0x8 /// method cannot be proxied to base tier
+
+#define CLS_LOG(level, fmt, ...)                                        \
+  cls_log(level, "<cls> %s:%d: " fmt, __FILE__, __LINE__, ##__VA_ARGS__)
+#define CLS_ERR(fmt, ...) CLS_LOG(0, fmt, ##__VA_ARGS__)
+
+/**
+ * Initialize a class.
+ */
+void __cls_init();
+
+/**
+ * @typdef cls_handle_t
+ *
+ * A handle for interacting with the object class.
+ */
+typedef void *cls_handle_t;
+
+/**
+ * @typedef cls_method_handle_t
+ *
+ * A handle for interacting with the method of the object class.
+ */
+typedef void *cls_method_handle_t;
+
+/**
+ * @typedef cls_method_context_t
+ *
+ * A context for the method of the object class.
+ */
+typedef void* cls_method_context_t;
+
+/*class utils*/
+extern int cls_log(int level, const char *format, ...)
+  __attribute__((__format__(printf, 2, 3)));
+
+/* class registration api */
+extern int cls_register(const char *name, cls_handle_t *handle);
+
+#ifdef __cplusplus
+}
+
+/**
+ * @typedef cls_method_cxx_call_t
+ *
+ */
+typedef int (*cls_method_cxx_call_t)(cls_method_context_t ctx,
+    class buffer::list *inbl, class buffer::list *outbl);
+
+/**
+ * Register a method.
+ *
+ * @param hclass
+ * @param method
+ * @param flags
+ * @param class_call
+ * @param handle
+ */
+extern int cls_register_cxx_method(cls_handle_t hclass, const char *method, int flags,
+                                   cls_method_cxx_call_t class_call, cls_method_handle_t *handle);
+
+/**
+ * Create an object.
+ *
+ * @param hctx
+ * @param exclusive
+ */
+extern int cls_cxx_create(cls_method_context_t hctx, bool exclusive);
+
+/**
+ * Remove an object.
+ *
+ * @param hctx
+ */
+extern int cls_cxx_remove(cls_method_context_t hctx);
+
+/**
+ * Check on the status of an object.
+ *
+ * @param hctx
+ * @param size
+ * @param mtime
+ */
+extern int cls_cxx_stat(cls_method_context_t hctx, uint64_t *size, time_t *mtime);
+
+/**
+ * Read contents of an object.
+ *
+ * @param hctx
+ * @param ofs
+ * @param len
+ * @param bl
+ */
+extern int cls_cxx_read(cls_method_context_t hctx, int ofs, int len, bufferlist *bl);
+
+/**
+ * Write to the object.
+ *
+ * @param hctx
+ * @param ofs
+ * @param len
+ * @param bl
+ */
+extern int cls_cxx_write(cls_method_context_t hctx, int ofs, int len, bufferlist *bl);
+
+/**
+ * Get xattr of the object.
+ *
+ * @param hctx
+ * @param name
+ * @param outbl
+ */
+extern int cls_cxx_getxattr(cls_method_context_t hctx, const char *name,
+                            bufferlist *outbl);
+
+/**
+ * Set xattr of the object.
+ *
+ * @param hctx
+ * @param name
+ * @param inbl
+ */
+extern int cls_cxx_setxattr(cls_method_context_t hctx, const char *name,
+                            bufferlist *inbl);
+
+/**
+ * Get value corresponding to a key from the map.
+ *
+ * @param hctx
+ * @param key
+ * @param outbl
+ */
+extern int cls_cxx_map_get_val(cls_method_context_t hctx,
+                               const std::string &key, bufferlist *outbl);
+
+/**
+ * Set value corresponding to a key in the map.
+ *
+ * @param hctx
+ * @param key
+ * @param inbl
+ */
+extern int cls_cxx_map_set_val(cls_method_context_t hctx,
+                               const std::string &key, bufferlist *inbl);
+
+#endif
+
+#endif
index a2418798f3205db082eb167b1f3b4ba843fdb950..99be19beb341372796e24c0705a99baa783f746c 100644 (file)
@@ -10,6 +10,7 @@
 #include "msg/msg_types.h"
 #include "common/hobject.h"
 #include "common/ceph_time.h"
+#include "include/rados/objclass.h"
 
 struct obj_list_watch_response_t;
 
@@ -22,40 +23,9 @@ struct obj_list_watch_response_t;
 extern "C" {
 #endif
 
-#ifndef BUILDING_FOR_EMBEDDED
-#define CLS_VER(maj,min) \
-int __cls_ver__## maj ## _ ##min = 0; \
-int __cls_ver_maj = maj; \
-int __cls_ver_min = min;
-
-#define CLS_NAME(name) \
-int __cls_name__## name = 0; \
-const char *__cls_name = #name;
-#define CLS_INIT(name) \
-void CEPH_CLS_API __cls_init()
-#else
-#define CLS_VER(maj,min)
-#define CLS_NAME(name)
-#define CLS_INIT(name) \
-void CEPH_CLS_API name##_cls_init()
-#endif
-
-#define CLS_METHOD_RD       0x1 /// method executes read operations
-#define CLS_METHOD_WR       0x2 /// method executes write operations
 #define CLS_METHOD_PUBLIC   0x4 /// unused
-#define CLS_METHOD_PROMOTE  0x8 /// method cannot be proxied to base tier
-
 
-#define CLS_LOG(level, fmt, ...)                                       \
-  cls_log(level, "<cls> %s:%d: " fmt, __FILE__, __LINE__, ##__VA_ARGS__)
-#define CLS_ERR(fmt, ...) CLS_LOG(0, fmt, ##__VA_ARGS__)
-
-void __cls_init();
-
-typedef void *cls_handle_t;
-typedef void *cls_method_handle_t;
 typedef void *cls_filter_handle_t;
-typedef void *cls_method_context_t;
 typedef int (*cls_method_call_t)(cls_method_context_t ctx,
                                 char *indata, int datalen,
                                 char **outdata, int *outdatalen);
@@ -65,8 +35,6 @@ typedef struct {
 } cls_deps_t;
 
 /* class utils */
-extern int cls_log(int level, const char *format, ...)
-  __attribute__((__format__(printf, 2, 3)));
 extern void *cls_alloc(size_t size);
 extern void cls_free(void *p);
 
@@ -85,7 +53,6 @@ extern int cls_get_request_origin(cls_method_context_t hctx,
                                   entity_inst_t *origin);
 
 /* class registration api */
-extern int cls_register(const char *name, cls_handle_t *handle);
 extern int cls_unregister(cls_handle_t);
 
 extern int cls_register_method(cls_handle_t hclass, const char *method, int flags,
@@ -113,9 +80,6 @@ extern void class_fini(void);
 #ifdef __cplusplus
 }
 
-typedef int (*cls_method_cxx_call_t)(cls_method_context_t ctx,
-                                    class buffer::list *inbl, class buffer::list *outbl);
-
 class PGLSFilter {
   CephContext* cct;
 protected:
@@ -150,30 +114,18 @@ public:
 typedef PGLSFilter* (*cls_cxx_filter_factory_t)();
 
 
-extern int cls_register_cxx_method(cls_handle_t hclass, const char *method, int flags,
-                                  cls_method_cxx_call_t class_call, cls_method_handle_t *handle);
-
 extern int cls_register_cxx_filter(cls_handle_t hclass,
                                    const std::string &filter_name,
                                   cls_cxx_filter_factory_t fn,
                                    cls_filter_handle_t *handle=NULL);
 
-extern int cls_cxx_create(cls_method_context_t hctx, bool exclusive);
-extern int cls_cxx_remove(cls_method_context_t hctx);
-extern int cls_cxx_stat(cls_method_context_t hctx, uint64_t *size, time_t *mtime);
 extern int cls_cxx_stat2(cls_method_context_t hctx, uint64_t *size, ceph::real_time *mtime);
-extern int cls_cxx_read(cls_method_context_t hctx, int ofs, int len, bufferlist *bl);
 extern int cls_cxx_read2(cls_method_context_t hctx, int ofs, int len,
                          bufferlist *bl, uint32_t op_flags);
-extern int cls_cxx_write(cls_method_context_t hctx, int ofs, int len, bufferlist *bl);
 extern int cls_cxx_write2(cls_method_context_t hctx, int ofs, int len,
                           bufferlist *bl, uint32_t op_flags);
 extern int cls_cxx_write_full(cls_method_context_t hctx, bufferlist *bl);
-extern int cls_cxx_getxattr(cls_method_context_t hctx, const char *name,
-                            bufferlist *outbl);
 extern int cls_cxx_getxattrs(cls_method_context_t hctx, map<string, bufferlist> *attrset);
-extern int cls_cxx_setxattr(cls_method_context_t hctx, const char *name,
-                            bufferlist *inbl);
 extern int cls_cxx_replace(cls_method_context_t hctx, int ofs, int len, bufferlist *bl);
 extern int cls_cxx_snap_revert(cls_method_context_t hctx, snapid_t snapid);
 extern int cls_cxx_map_clear(cls_method_context_t hctx);
@@ -189,10 +141,6 @@ extern int cls_cxx_map_get_vals(cls_method_context_t hctx,
                                 uint64_t max_to_get,
                                 std::map<string, bufferlist> *vals);
 extern int cls_cxx_map_read_header(cls_method_context_t hctx, bufferlist *outbl);
-extern int cls_cxx_map_get_val(cls_method_context_t hctx,
-                               const string &key, bufferlist *outbl);
-extern int cls_cxx_map_set_val(cls_method_context_t hctx,
-                               const string &key, bufferlist *inbl);
 extern int cls_cxx_map_set_vals(cls_method_context_t hctx,
                                 const std::map<string, bufferlist> *map);
 extern int cls_cxx_map_write_header(cls_method_context_t hctx, bufferlist *inbl);
index 378a1563b056b6663ced4fd282100a79681a1aba..82d3fea331045b61b2577c28fce2490bb425e21b 100644 (file)
@@ -12,6 +12,7 @@ add_subdirectory(cls_hello)
 add_subdirectory(cls_lock)
 add_subdirectory(cls_log)
 add_subdirectory(cls_numops)
+add_subdirectory(cls_sdk)
 if(WITH_RBD)
   add_subdirectory(cls_rbd)
 endif(WITH_RBD)
diff --git a/src/test/cls_sdk/CMakeLists.txt b/src/test/cls_sdk/CMakeLists.txt
new file mode 100644 (file)
index 0000000..2579b9c
--- /dev/null
@@ -0,0 +1,17 @@
+add_executable(ceph_test_cls_sdk
+  test_cls_sdk.cc
+  )
+set_target_properties(ceph_test_cls_sdk PROPERTIES COMPILE_FLAGS
+  ${UNITTEST_CXX_FLAGS})
+target_link_libraries(ceph_test_cls_sdk
+  librados
+  global
+  ${EXTRALIBS}
+  ${BLKID_LIBRARIES}
+  ${CMAKE_DL_LIBS}
+  radostest
+  ${UNITTEST_LIBS}
+  )
+install(TARGETS
+  ceph_test_cls_sdk
+  DESTINATION ${CMAKE_INSTALL_BINDIR})
diff --git a/src/test/cls_sdk/test_cls_sdk.cc b/src/test/cls_sdk/test_cls_sdk.cc
new file mode 100644 (file)
index 0000000..af3452b
--- /dev/null
@@ -0,0 +1,35 @@
+#include <iostream>
+#include <errno.h>
+
+#include "test/librados/test.h"
+#include "gtest/gtest.h"
+
+using namespace librados;
+
+TEST(ClsSDK, TestSDKCoverageWrite) {
+  Rados cluster;
+  std::string pool_name = get_temp_pool_name();
+  ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
+  IoCtx ioctx;
+  cluster.ioctx_create(pool_name.c_str(), ioctx);
+
+  bufferlist in, out;
+  ASSERT_EQ(0, ioctx.exec("myobject", "sdk", "test_coverage_write", in, out));
+
+  ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
+}
+
+TEST(ClsSDK, TestSDKCoverageReplay) {
+  Rados cluster;
+  std::string pool_name = get_temp_pool_name();
+  ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
+  IoCtx ioctx;
+  cluster.ioctx_create(pool_name.c_str(), ioctx);
+
+  bufferlist in, out;
+  ASSERT_EQ(0, ioctx.exec("myobject", "sdk", "test_coverage_write", in, out));
+  ASSERT_EQ(0, ioctx.exec("myobject", "sdk", "test_coverage_replay", in, out));
+
+  ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
+}
+