librbd: added trash_get API method to retrieve image status

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
This commit is contained in:
Jason Dillaman 2017-04-28 14:51:41 -04:00
parent 4b48b9fe68
commit 4939ff707b
8 changed files with 136 additions and 14 deletions

View 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,

View 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);

View 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;

View 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,

View 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]);
}
}

View 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.

View 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());

View 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: