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);
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,
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);
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;
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,
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;
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,
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;
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();
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]);
}
}
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,
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.
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());
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: