]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: added trash_get API method to retrieve image status
authorJason Dillaman <dillaman@redhat.com>
Fri, 28 Apr 2017 18:51:41 +0000 (14:51 -0400)
committerJason Dillaman <dillaman@redhat.com>
Mon, 1 May 2017 14:10:16 +0000 (10:10 -0400)
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/include/rbd/librbd.h
src/include/rbd/librbd.hpp
src/librbd/internal.cc
src/librbd/internal.h
src/librbd/librbd.cc
src/pybind/rbd/rbd.pyx
src/test/librbd/test_librbd.cc
src/test/pybind/test_rbd.py

index 289640a499da110a61c763ce89be5434d72d587a..87d04eb44706badce71dab6c8683437b46e58e2e 100644 (file)
@@ -255,8 +255,14 @@ CEPH_RBD_API int rbd_remove(rados_ioctx_t io, const char *name);
 CEPH_RBD_API int rbd_remove_with_progress(rados_ioctx_t io, const char *name,
                                          librbd_progress_fn_t cb,
                                           void *cbdata);
+CEPH_RBD_API int rbd_rename(rados_ioctx_t src_io_ctx, const char *srcname,
+                            const char *destname);
+
 CEPH_RBD_API int rbd_trash_move(rados_ioctx_t io, const char *name,
                                 uint64_t delay);
+CEPH_RBD_API int rbd_trash_get(rados_ioctx_t io, const char *id,
+                               rbd_trash_image_info_t *info);
+CEPH_RBD_API void rbd_trash_get_cleanup(rbd_trash_image_info_t *info);
 CEPH_RBD_API int rbd_trash_list(rados_ioctx_t io,
                                 rbd_trash_image_info_t *trash_entries,
                                 size_t *num_entries);
@@ -268,8 +274,6 @@ CEPH_RBD_API int rbd_trash_remove_with_progress(rados_ioctx_t io, const char *id
                                                 void *cbdata);
 CEPH_RBD_API int rbd_trash_restore(rados_ioctx_t io, const char *id,
                                    const char *name);
-CEPH_RBD_API int rbd_rename(rados_ioctx_t src_io_ctx, const char *srcname,
-                            const char *destname);
 
 /* pool mirroring */
 CEPH_RBD_API int rbd_mirror_mode_get(rados_ioctx_t io_ctx,
index d774b9d10ae6bb254326bbcc38b53b667d031b79..f03ca9f362209e42549e002249ebd89799aa3928 100644 (file)
@@ -158,15 +158,16 @@ public:
             IoCtx& c_ioctx, const char *c_name, ImageOptions& opts);
   int remove(IoCtx& io_ctx, const char *name);
   int remove_with_progress(IoCtx& io_ctx, const char *name, ProgressContext& pctx);
+  int rename(IoCtx& src_io_ctx, const char *srcname, const char *destname);
+
   int trash_move(IoCtx &io_ctx, const char *name, uint64_t delay);
+  int trash_get(IoCtx &io_ctx, const char *id, trash_image_info_t *info);
   int trash_list(IoCtx &io_ctx, std::vector<trash_image_info_t> &entries);
   int trash_remove(IoCtx &io_ctx, const char *image_id, bool force);
-  int trash_remove_with_progress(IoCtx &io_ctx, const char *image_id, bool force,
-                                 ProgressContext &pctx);
+  int trash_remove_with_progress(IoCtx &io_ctx, const char *image_id,
+                                 bool force, ProgressContext &pctx);
   int trash_restore(IoCtx &io_ctx, const char *id, const char *name);
 
-  int rename(IoCtx& src_io_ctx, const char *srcname, const char *destname);
-
   // RBD pool mirroring support functions
   int mirror_mode_get(IoCtx& io_ctx, rbd_mirror_mode_t *mirror_mode);
   int mirror_mode_set(IoCtx& io_ctx, rbd_mirror_mode_t mirror_mode);
index 1168afac7f730d706d3483e335b4283c64a2e4d4..bfdd5fb7fbc1ead063d927b05a47567fe2d73765 100644 (file)
@@ -1433,6 +1433,28 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) {
     return 0;
   }
 
+  int trash_get(IoCtx &io_ctx, const std::string &id,
+                trash_image_info_t *info) {
+    CephContext *cct((CephContext *)io_ctx.cct());
+    ldout(cct, 20) << __func__ << " " << &io_ctx << dendl;
+
+    cls::rbd::TrashImageSpec spec;
+    int r = cls_client::trash_get(&io_ctx, id, &spec);
+    if (r == -ENOENT) {
+      return r;
+    } else if (r < 0) {
+      lderr(cct) << "error retrieving trash entry: " << cpp_strerror(r)
+                 << dendl;
+      return r;
+    }
+
+    rbd_trash_image_source_t source = static_cast<rbd_trash_image_source_t>(
+      spec.source);
+    *info = trash_image_info_t{id, spec.name, source, spec.deletion_time.sec(),
+                               spec.deferment_end_time.sec()};
+    return 0;
+  }
+
   int trash_list(IoCtx &io_ctx, vector<trash_image_info_t> &entries) {
     CephContext *cct((CephContext *)io_ctx.cct());
     ldout(cct, 20) << "trash_list " << &io_ctx << dendl;
index cf07472b1af0e92d2e233f2b8e44d0f2c26149b4..deeaf9455957b9e2e3beb40af20c6c37959af893 100644 (file)
@@ -143,8 +143,10 @@ namespace librbd {
   int remove(librados::IoCtx& io_ctx, const std::string &image_name,
              const std::string &image_id, ProgressContext& prog_ctx,
              bool force=false, bool from_trash_remove=false);
+
   int trash_move(librados::IoCtx &io_ctx, rbd_trash_image_source_t source,
                  const std::string &image_name, uint64_t delay);
+  int trash_get(IoCtx &io_ctx, const std::string &id, trash_image_info_t *info);
   int trash_list(librados::IoCtx &io_ctx,
                  std::vector<trash_image_info_t> &entries);
   int trash_remove(librados::IoCtx &io_ctx, const std::string &image_id,
index a2180170cf3e2eed7b679cfde9adc60734049bcb..8094433ee5f035d23cfdb1fb5ec81a4de373b6a4 100644 (file)
@@ -184,6 +184,15 @@ void mirror_image_status_cpp_to_c(const librbd::mirror_image_status_t &cpp_statu
   c_status->up = cpp_status.up;
 }
 
+void trash_image_info_cpp_to_c(const librbd::trash_image_info_t &cpp_info,
+                               rbd_trash_image_info_t *c_info) {
+  c_info->id = strdup(cpp_info.id.c_str());
+  c_info->name = strdup(cpp_info.name.c_str());
+  c_info->source = cpp_info.source;
+  c_info->deletion_time = cpp_info.deletion_time;
+  c_info->deferment_end_time = cpp_info.deferment_end_time;
+}
+
 struct C_MirrorImageGetInfo : public Context {
     rbd_mirror_image_info_t *mirror_image_info;
   Context *on_finish;
@@ -551,6 +560,10 @@ namespace librbd {
     return r;
   }
 
+  int RBD::trash_get(IoCtx &io_ctx, const char *id, trash_image_info_t *info) {
+    return librbd::trash_get(io_ctx, id, info);
+  }
+
   int RBD::trash_list(IoCtx &io_ctx, vector<trash_image_info_t> &entries) {
     TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
     tracepoint(librbd, trash_list_enter,
@@ -2295,6 +2308,26 @@ extern "C" int rbd_trash_move(rados_ioctx_t p, const char *name,
   return r;
 }
 
+extern "C" int rbd_trash_get(rados_ioctx_t io, const char *id,
+                             rbd_trash_image_info_t *info) {
+  librados::IoCtx io_ctx;
+  librados::IoCtx::from_rados_ioctx_t(io, io_ctx);
+
+  librbd::trash_image_info_t cpp_info;
+  int r = librbd::trash_get(io_ctx, id, &cpp_info);
+  if (r < 0) {
+    return r;
+  }
+
+  trash_image_info_cpp_to_c(cpp_info, info);
+  return 0;
+}
+
+extern "C" void rbd_trash_get_cleanup(rbd_trash_image_info_t *info) {
+  free(info->id);
+  free(info->name);
+}
+
 extern "C" int rbd_trash_list(rados_ioctx_t p, rbd_trash_image_info_t *entries,
                               size_t *num_entries) {
   librados::IoCtx io_ctx;
@@ -2318,12 +2351,7 @@ extern "C" int rbd_trash_list(rados_ioctx_t p, rbd_trash_image_info_t *entries,
 
   int i=0;
   for (const auto &entry : cpp_entries) {
-    entries[i].id = strdup(entry.id.c_str());
-    entries[i].name = strdup(entry.name.c_str());
-    entries[i].source = entry.source;
-    entries[i].deletion_time = entry.deletion_time;
-    entries[i].deferment_end_time = entry.deferment_end_time;
-    i++;
+    trash_image_info_cpp_to_c(entry, &entries[i++]);
   }
   *num_entries = cpp_entries.size();
 
@@ -2333,8 +2361,7 @@ extern "C" int rbd_trash_list(rados_ioctx_t p, rbd_trash_image_info_t *entries,
 extern "C" void rbd_trash_list_cleanup(rbd_trash_image_info_t *entries,
                                        size_t num_entries) {
   for (size_t i=0; i < num_entries; i++) {
-    free(entries[i].id);
-    free(entries[i].name);
+    rbd_trash_get_cleanup(&entries[i]);
   }
 }
 
index 3457fcc0a675a560b3c3401818fd1782905ddd3f..aa212cced86f5db0d83cba67715e9fdacb6f309b 100644 (file)
@@ -180,6 +180,9 @@ cdef extern from "rbd/librbd.h" nogil:
                    const char *destname)
 
     int rbd_trash_move(rados_ioctx_t io, const char *name, uint64_t delay)
+    int rbd_trash_get(rados_ioctx_t io, const char *id,
+                      rbd_trash_image_info_t *info)
+    void rbd_trash_get_cleanup(rbd_trash_image_info_t *info)
     int rbd_trash_list(rados_ioctx_t io, rbd_trash_image_info_t *trash_entries,
                        size_t *num_entries)
     void rbd_trash_list_cleanup(rbd_trash_image_info_t *trash_entries,
@@ -920,6 +923,49 @@ class RBD(object):
         if ret != 0:
             raise make_ex(ret, 'error deleting image from trash')
 
+    def trash_get(self, ioctx, image_id):
+        """
+        Retrieve RBD image info from trash
+        :param ioctx: determines which RADOS pool the image is in
+        :type ioctx: :class:`rados.Ioctx`
+        :param image_id: the id of the image to restore
+        :type image_id: str
+        :returns: dict - contains the following keys:
+
+            * ``id`` (str) - image id
+
+            * ``name`` (str) - image name
+
+            * ``source`` (str) - source of deletion
+
+            * ``deletion_time`` (datetime) - time of deletion
+
+            * ``deferment_end_time`` (datetime) - time that an image is allowed
+              to be removed from trash
+
+        :raises: :class:`ImageNotFound`
+        """
+        image_id = cstr(image_id, 'image_id')
+        cdef:
+            rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+            char *_image_id = image_id
+            rbd_trash_image_info_t c_info
+        with nogil:
+            ret = rbd_trash_get(_ioctx, _image_id, &c_info)
+        if ret != 0:
+            raise make_ex(ret, 'error restoring image from trash')
+
+        __source_string = ['USER', 'MIRRORING']
+        info = {
+            'id'          : decode_cstr(c_info.id),
+            'name'        : decode_cstr(c_info.name),
+            'source'      : __source_string[c_info.source],
+            'deletion_time' : datetime.fromtimestamp(c_info.deletion_time),
+            'deferment_end_time' : datetime.fromtimestamp(c_info.deferment_end_time)
+            }
+        rbd_trash_get_cleanup(&c_info)
+        return info
+
     def trash_list(self, ioctx):
         """
         Lists all entries from trash.
index 3d2089480922f04f039ccb02e552a1950959771c..e00bfba9b1a648deed71ab6404d01f9fc00ece49 100644 (file)
@@ -5738,6 +5738,11 @@ TEST_F(TestLibRBD, TestTrashMoveAndPurge) {
     ASSERT_TRUE(image != name);
   }
 
+  librbd::trash_image_info_t info;
+  ASSERT_EQ(-ENOENT, rbd.trash_get(ioctx, "dummy image id", &info));
+  ASSERT_EQ(0, rbd.trash_get(ioctx, image_id.c_str(), &info));
+  ASSERT_EQ(image_id, info.id);
+
   std::vector<librbd::trash_image_info_t> entries;
   ASSERT_EQ(0, rbd.trash_list(ioctx, entries));
   ASSERT_FALSE(entries.empty());
index 57c35fd82c81786d23a34c44cd27d02bc0f4e30e..b01b7390bfdf640a051254a8115808f3562c04d7 100644 (file)
@@ -1501,6 +1501,21 @@ class TestTrash(object):
         RBD().trash_move(ioctx, image_name, 0)
         RBD().trash_remove(ioctx, image_id)
 
+    def test_get(self):
+        create_image()
+        with Image(ioctx, image_name) as image:
+            image_id = image.id()
+
+        RBD().trash_move(ioctx, image_name, 1000)
+
+        info = RBD().trash_get(ioctx, image_id)
+        eq(image_id, info['id'])
+        eq(image_name, info['name'])
+        eq('USER', info['source'])
+        assert(info['deferment_end_time'] > info['deletion_time'])
+
+        RBD().trash_remove(ioctx, image_id, True)
+
     def test_list(self):
         create_image()
         with Image(ioctx, image_name) as image: