From 17dd40df4f4201cf0c0c6d58b1728177c5ee726b Mon Sep 17 00:00:00 2001 From: Mykola Golub Date: Tue, 5 Apr 2016 14:24:07 +0300 Subject: [PATCH] cls::rbd:: methods to store/retrieve mirroring status Signed-off-by: Mykola Golub --- src/cls/rbd/cls_rbd.cc | 473 ++++++++++++++++++++++++++++++++++ src/cls/rbd/cls_rbd_client.cc | 158 ++++++++++++ src/cls/rbd/cls_rbd_client.h | 34 +++ src/cls/rbd/cls_rbd_types.cc | 84 ++++++ src/cls/rbd/cls_rbd_types.h | 52 ++++ 5 files changed, 801 insertions(+) diff --git a/src/cls/rbd/cls_rbd.cc b/src/cls/rbd/cls_rbd.cc index ad7d6b1a39c1f..1b38eabfbe190 100644 --- a/src/cls/rbd/cls_rbd.cc +++ b/src/cls/rbd/cls_rbd.cc @@ -40,6 +40,7 @@ #include "common/bit_vector.hpp" #include "common/errno.h" #include "objclass/objclass.h" +#include "osd/osd_types.h" #include "include/rbd_types.h" #include "include/rbd/object_map_types.h" @@ -125,6 +126,12 @@ cls_method_handle_t h_mirror_image_get_image_id; cls_method_handle_t h_mirror_image_get; cls_method_handle_t h_mirror_image_set; cls_method_handle_t h_mirror_image_remove; +cls_method_handle_t h_mirror_image_status_set; +cls_method_handle_t h_mirror_image_status_remove; +cls_method_handle_t h_mirror_image_status_get; +cls_method_handle_t h_mirror_image_status_list; +cls_method_handle_t h_mirror_image_status_get_summary; +cls_method_handle_t h_mirror_image_status_remove_down; #define RBD_MAX_KEYS_READ 64 #define RBD_SNAP_KEY_PREFIX "snapshot_" @@ -2965,6 +2972,7 @@ static const std::string MODE("mirror_mode"); static const std::string PEER_KEY_PREFIX("mirror_peer_"); static const std::string IMAGE_KEY_PREFIX("image_"); static const std::string GLOBAL_KEY_PREFIX("global_"); +static const std::string STATUS_GLOBAL_KEY_PREFIX("status_global_"); std::string peer_key(const std::string &uuid) { return PEER_KEY_PREFIX + uuid; @@ -2978,6 +2986,10 @@ std::string global_key(const string &global_id) { return GLOBAL_KEY_PREFIX + global_id; } +std::string status_global_key(const string &global_id) { + return STATUS_GLOBAL_KEY_PREFIX + global_id; +} + int uuid_get(cls_method_context_t hctx, std::string *mirror_uuid) { bufferlist mirror_uuid_bl; int r = cls_cxx_map_get_val(hctx, mirror::UUID, &mirror_uuid_bl); @@ -3162,6 +3174,296 @@ int image_remove(cls_method_context_t hctx, const string &image_id) { return 0; } +struct MirrorImageStatusOnDisk : cls::rbd::MirrorImageStatus { + entity_inst_t origin; + + MirrorImageStatusOnDisk() { + } + MirrorImageStatusOnDisk(const cls::rbd::MirrorImageStatus &status) : + cls::rbd::MirrorImageStatus(status) { + } + + void encode_meta(bufferlist &bl) const { + ENCODE_START(1, 1, bl); + ::encode(origin, bl); + ENCODE_FINISH(bl); + } + + void encode(bufferlist &bl) const { + encode_meta(bl); + cls::rbd::MirrorImageStatus::encode(bl); + } + + void decode_meta(bufferlist::iterator &it) { + DECODE_START(1, it); + ::decode(origin, it); + DECODE_FINISH(it); + } + + void decode(bufferlist::iterator &it) { + decode_meta(it); + cls::rbd::MirrorImageStatus::decode(it); + } +}; +WRITE_CLASS_ENCODER(MirrorImageStatusOnDisk) + +int image_status_set(cls_method_context_t hctx, const string &global_image_id, + const cls::rbd::MirrorImageStatus &status) { + MirrorImageStatusOnDisk ondisk_status(status); + ondisk_status.up = false; + ondisk_status.last_update = ceph_clock_now(g_ceph_context); + + int r = cls_get_request_origin(hctx, &ondisk_status.origin); + assert(r == 0); + + bufferlist bl; + encode(ondisk_status, bl); + + r = cls_cxx_map_set_val(hctx, status_global_key(global_image_id), &bl); + if (r < 0) { + CLS_ERR("error setting status for mirrored image, global id '%s': %s", + global_image_id.c_str(), cpp_strerror(r).c_str()); + return r; + } + return 0; +} + +int image_status_remove(cls_method_context_t hctx, + const string &global_image_id) { + + int r = cls_cxx_map_remove_key(hctx, status_global_key(global_image_id)); + if (r < 0) { + CLS_ERR("error removing status for mirrored image, global id '%s': %s", + global_image_id.c_str(), cpp_strerror(r).c_str()); + return r; + } + return 0; +} + +int image_status_get(cls_method_context_t hctx, const string &global_image_id, + cls::rbd::MirrorImageStatus *status) { + + bufferlist bl; + int r = cls_cxx_map_get_val(hctx, status_global_key(global_image_id), &bl); + if (r < 0) { + if (r != -ENOENT) { + CLS_ERR("error reading status for mirrored image, global id '%s': '%s'", + global_image_id.c_str(), cpp_strerror(r).c_str()); + } + return r; + } + + MirrorImageStatusOnDisk ondisk_status; + try { + bufferlist::iterator it = bl.begin(); + decode(ondisk_status, it); + } catch (const buffer::error &err) { + CLS_ERR("could not decode status for mirrored image, global id '%s'", + global_image_id.c_str()); + return -EIO; + } + + obj_list_watch_response_t watchers; + r = cls_cxx_list_watchers(hctx, &watchers); + if (r < 0 && r != -ENOENT) { + CLS_ERR("error listing watchers: '%s'", cpp_strerror(r).c_str()); + return r; + } + + *status = static_cast(ondisk_status); + status->up = false; + for (auto &w : watchers.entries) { + if (w.name == ondisk_status.origin.name && + w.addr == ondisk_status.origin.addr) { + status->up = true; + break; + } + } + + return 0; +} + +int image_status_list(cls_method_context_t hctx, + const std::string &start_after, uint64_t max_return, + map *mirror_images, + map *mirror_statuses) { + std::string last_read = image_key(start_after); + int max_read = RBD_MAX_KEYS_READ; + int r = max_read; + + while (r == max_read && mirror_images->size() < max_return) { + std::map vals; + CLS_LOG(20, "last_read = '%s'", last_read.c_str()); + r = cls_cxx_map_get_vals(hctx, last_read, IMAGE_KEY_PREFIX, max_read, + &vals); + if (r < 0) { + CLS_ERR("error reading mirror image directory by name: %s", + cpp_strerror(r).c_str()); + return r; + } + + for (auto it = vals.begin(); it != vals.end() && + mirror_images->size() < max_return; ++it) { + const std::string &image_id = it->first.substr(IMAGE_KEY_PREFIX.size()); + cls::rbd::MirrorImage mirror_image; + bufferlist::iterator iter = it->second.begin(); + try { + ::decode(mirror_image, iter); + } catch (const buffer::error &err) { + CLS_ERR("could not decode mirror image payload of image '%s'", + image_id.c_str()); + return -EIO; + } + + (*mirror_images)[image_id] = mirror_image; + + cls::rbd::MirrorImageStatus status; + r = image_status_get(hctx, mirror_image.global_image_id, &status); + if (r < 0) { + continue; + } + + (*mirror_statuses)[image_id] = status; + } + if (!vals.empty()) { + last_read = image_key(mirror_images->rbegin()->first); + } + } + + return 0; +} + +int image_status_get_summary(cls_method_context_t hctx, + std::map *states) { + obj_list_watch_response_t watchers_; + int r = cls_cxx_list_watchers(hctx, &watchers_); + if (r < 0) { + if (r != -ENOENT) { + CLS_ERR("error listing watchers: '%s'", cpp_strerror(r).c_str()); + } + return r; + } + + set watchers; + for (auto &w : watchers_.entries) { + watchers.insert(entity_inst_t(w.name, w.addr)); + } + + states->clear(); + + string last_read = IMAGE_KEY_PREFIX; + int max_read = RBD_MAX_KEYS_READ; + r = max_read; + while (r == max_read) { + map vals; + r = cls_cxx_map_get_vals(hctx, last_read, IMAGE_KEY_PREFIX, + max_read, &vals); + if (r < 0) { + CLS_ERR("error reading mirrored images: %s", cpp_strerror(r).c_str()); + return r; + } + + for (auto &list_it : vals) { + const string &key = list_it.first; + + if (0 != key.compare(0, IMAGE_KEY_PREFIX.size(), IMAGE_KEY_PREFIX)) { + break; + } + + cls::rbd::MirrorImage mirror_image; + bufferlist::iterator iter = list_it.second.begin(); + try { + ::decode(mirror_image, iter); + } catch (const buffer::error &err) { + CLS_ERR("could not decode mirror image payload for key '%s'", + key.c_str()); + return -EIO; + } + + cls::rbd::MirrorImageStatus status; + r = image_status_get(hctx, mirror_image.global_image_id, &status); + if (r < 0) { + // Ignore. + } + + cls::rbd::MirrorImageStatusState state = status.up ? status.state : + cls::rbd::MIRROR_IMAGE_STATUS_STATE_UNKNOWN; + (*states)[state]++; + } + + if (!vals.empty()) { + last_read = vals.rbegin()->first; + } + } + + return 0; +} + +int image_status_remove_down(cls_method_context_t hctx) { + obj_list_watch_response_t watchers_; + int r = cls_cxx_list_watchers(hctx, &watchers_); + if (r < 0) { + if (r != -ENOENT) { + CLS_ERR("error listing watchers: '%s'", cpp_strerror(r).c_str()); + } + return r; + } + + set watchers; + for (auto &w : watchers_.entries) { + watchers.insert(entity_inst_t(w.name, w.addr)); + } + + string last_read = STATUS_GLOBAL_KEY_PREFIX; + int max_read = RBD_MAX_KEYS_READ; + r = max_read; + while (r == max_read) { + map vals; + r = cls_cxx_map_get_vals(hctx, last_read, STATUS_GLOBAL_KEY_PREFIX, + max_read, &vals); + if (r < 0) { + CLS_ERR("error reading mirrored images: %s", cpp_strerror(r).c_str()); + return r; + } + + for (auto &list_it : vals) { + const string &key = list_it.first; + + if (0 != key.compare(0, STATUS_GLOBAL_KEY_PREFIX.size(), + STATUS_GLOBAL_KEY_PREFIX)) { + break; + } + + MirrorImageStatusOnDisk status; + try { + bufferlist::iterator it = list_it.second.begin(); + status.decode_meta(it); + } catch (const buffer::error &err) { + CLS_ERR("could not decode status metadata for mirrored image '%s'", + key.c_str()); + return -EIO; + } + + if (watchers.find(status.origin) == watchers.end()) { + CLS_LOG(20, "removing stale status object for key %s", + key.c_str()); + int r1 = cls_cxx_map_remove_key(hctx, key); + if (r1 < 0) { + CLS_ERR("error removing stale status for key '%s': %s", + key.c_str(), cpp_strerror(r1).c_str()); + return r1; + } + } + } + + if (!vals.empty()) { + last_read = vals.rbegin()->first; + } + } + + return 0; +} + } // namespace mirror /** @@ -3676,6 +3978,158 @@ int mirror_image_remove(cls_method_context_t hctx, bufferlist *in, return 0; } +/** + * Input: + * @param global_image_id (std::string) + * @param status (cls::rbd::MirrorImageStatus) + * + * Output: + * @returns 0 on success, negative error code on failure + */ +int mirror_image_status_set(cls_method_context_t hctx, bufferlist *in, + bufferlist *out) { + string global_image_id; + cls::rbd::MirrorImageStatus status; + try { + bufferlist::iterator it = in->begin(); + ::decode(global_image_id, it); + ::decode(status, it); + } catch (const buffer::error &err) { + return -EINVAL; + } + + int r = mirror::image_status_set(hctx, global_image_id, status); + if (r < 0) { + return r; + } + return 0; +} + +/** + * Input: + * @param global_image_id (std::string) + * + * Output: + * @returns 0 on success, negative error code on failure + */ +int mirror_image_status_remove(cls_method_context_t hctx, bufferlist *in, + bufferlist *out) { + string global_image_id; + try { + bufferlist::iterator it = in->begin(); + ::decode(global_image_id, it); + } catch (const buffer::error &err) { + return -EINVAL; + } + + int r = mirror::image_status_remove(hctx, global_image_id); + if (r < 0) { + return r; + } + return 0; +} + +/** + * Input: + * @param global_image_id (std::string) + * + * Output: + * @param cls::rbd::MirrorImageStatus - metadata associated with the global_image_id + * @returns 0 on success, negative error code on failure + */ +int mirror_image_status_get(cls_method_context_t hctx, bufferlist *in, + bufferlist *out) { + string global_image_id; + try { + bufferlist::iterator it = in->begin(); + ::decode(global_image_id, it); + } catch (const buffer::error &err) { + return -EINVAL; + } + + cls::rbd::MirrorImageStatus status; + int r = mirror::image_status_get(hctx, global_image_id, &status); + if (r < 0) { + return r; + } + + ::encode(status, *out); + return 0; +} + +/** + * Input: + * @param start_after which name to begin listing after + * (use the empty string to start at the beginning) + * @param max_return the maximum number of names to list + * + * Output: + * @param std::map: image id to image map + * @param std::map: image it to status map + * @returns 0 on success, negative error code on failure + */ +int mirror_image_status_list(cls_method_context_t hctx, bufferlist *in, + bufferlist *out) { + std::string start_after; + uint64_t max_return; + try { + bufferlist::iterator iter = in->begin(); + ::decode(start_after, iter); + ::decode(max_return, iter); + } catch (const buffer::error &err) { + return -EINVAL; + } + + map images; + map statuses; + int r = mirror::image_status_list(hctx, start_after, max_return, &images, + &statuses); + if (r < 0) { + return r; + } + + ::encode(images, *out); + ::encode(statuses, *out); + return 0; +} + +/** + * Input: + * none + * + * Output: + * @param std::map: states counts + * @returns 0 on success, negative error code on failure + */ +int mirror_image_status_get_summary(cls_method_context_t hctx, bufferlist *in, + bufferlist *out) { + std::map states; + + int r = mirror::image_status_get_summary(hctx, &states); + if (r < 0) { + return r; + } + + ::encode(states, *out); + return 0; +} + +/** + * Input: + * none + * + * Output: + * @returns 0 on success, negative error code on failure + */ +int mirror_image_status_remove_down(cls_method_context_t hctx, bufferlist *in, + bufferlist *out) { + int r = mirror::image_status_remove_down(hctx); + if (r < 0) { + return r; + } + return 0; +} + void __cls_init() { CLS_LOG(20, "Loaded rbd class!"); @@ -3871,5 +4325,24 @@ void __cls_init() cls_register_cxx_method(h_class, "mirror_image_remove", CLS_METHOD_RD | CLS_METHOD_WR, mirror_image_remove, &h_mirror_image_remove); + cls_register_cxx_method(h_class, "mirror_image_status_set", + CLS_METHOD_RD | CLS_METHOD_WR | CLS_METHOD_PROMOTE, + mirror_image_status_set, &h_mirror_image_status_set); + cls_register_cxx_method(h_class, "mirror_image_status_remove", + CLS_METHOD_RD | CLS_METHOD_WR, + mirror_image_status_remove, + &h_mirror_image_status_remove); + cls_register_cxx_method(h_class, "mirror_image_status_get", CLS_METHOD_RD, + mirror_image_status_get, &h_mirror_image_status_get); + cls_register_cxx_method(h_class, "mirror_image_status_list", CLS_METHOD_RD, + mirror_image_status_list, + &h_mirror_image_status_list); + cls_register_cxx_method(h_class, "mirror_image_status_get_summary", + CLS_METHOD_RD, mirror_image_status_get_summary, + &h_mirror_image_status_get_summary); + cls_register_cxx_method(h_class, "mirror_image_status_remove_down", + CLS_METHOD_RD | CLS_METHOD_WR, + mirror_image_status_remove_down, + &h_mirror_image_status_remove_down); return; } diff --git a/src/cls/rbd/cls_rbd_client.cc b/src/cls/rbd/cls_rbd_client.cc index 5fe8452028a9f..ec57f7f8daae2 100644 --- a/src/cls/rbd/cls_rbd_client.cc +++ b/src/cls/rbd/cls_rbd_client.cc @@ -1236,5 +1236,163 @@ namespace librbd { return 0; } + int mirror_image_status_set(librados::IoCtx *ioctx, + const std::string &global_image_id, + const cls::rbd::MirrorImageStatus &status) { + librados::ObjectWriteOperation op; + mirror_image_status_set(&op, global_image_id, status); + return ioctx->operate(RBD_MIRRORING, &op); + } + + void mirror_image_status_set(librados::ObjectWriteOperation *op, + const std::string &global_image_id, + const cls::rbd::MirrorImageStatus &status) { + bufferlist bl; + ::encode(global_image_id, bl); + ::encode(status, bl); + op->exec("rbd", "mirror_image_status_set", bl); + } + + int mirror_image_status_remove(librados::IoCtx *ioctx, + const std::string &global_image_id) { + librados::ObjectWriteOperation op; + mirror_image_status_remove(&op, global_image_id); + return ioctx->operate(RBD_MIRRORING, &op); + } + + void mirror_image_status_remove(librados::ObjectWriteOperation *op, + const std::string &global_image_id) { + bufferlist bl; + ::encode(global_image_id, bl); + op->exec("rbd", "mirror_image_status_remove", bl); + } + + int mirror_image_status_get(librados::IoCtx *ioctx, + const std::string &global_image_id, + cls::rbd::MirrorImageStatus *status) { + librados::ObjectReadOperation op; + mirror_image_status_get_start(&op, global_image_id); + + bufferlist out_bl; + int r = ioctx->operate(RBD_MIRRORING, &op, &out_bl); + if (r < 0) { + return r; + } + + bufferlist::iterator iter = out_bl.begin(); + r = mirror_image_status_get_finish(&iter, status); + if (r < 0) { + return r; + } + return 0; + } + + void mirror_image_status_get_start(librados::ObjectReadOperation *op, + const std::string &global_image_id) { + bufferlist bl; + ::encode(global_image_id, bl); + op->exec("rbd", "mirror_image_status_get", bl); + } + + int mirror_image_status_get_finish(bufferlist::iterator *iter, + cls::rbd::MirrorImageStatus *status) { + try { + ::decode(*status, *iter); + } catch (const buffer::error &err) { + return -EBADMSG; + } + return 0; + } + + int mirror_image_status_list(librados::IoCtx *ioctx, + const std::string &start, uint64_t max_return, + std::map *images, + std::map *statuses) { + librados::ObjectReadOperation op; + mirror_image_status_list_start(&op, start, max_return); + + bufferlist out_bl; + int r = ioctx->operate(RBD_MIRRORING, &op, &out_bl); + if (r < 0) { + return r; + } + + bufferlist::iterator iter = out_bl.begin(); + r = mirror_image_status_list_finish(&iter, images, statuses); + if (r < 0) { + return r; + } + return 0; + } + + void mirror_image_status_list_start(librados::ObjectReadOperation *op, + const std::string &start, + uint64_t max_return) { + bufferlist bl; + ::encode(start, bl); + ::encode(max_return, bl); + op->exec("rbd", "mirror_image_status_list", bl); + } + + int mirror_image_status_list_finish(bufferlist::iterator *iter, + std::map *images, + std::map *statuses) { + images->clear(); + statuses->clear(); + try { + ::decode(*images, *iter); + ::decode(*statuses, *iter); + } catch (const buffer::error &err) { + return -EBADMSG; + } + return 0; + } + + int mirror_image_status_get_summary(librados::IoCtx *ioctx, + std::map *states) { + librados::ObjectReadOperation op; + mirror_image_status_get_summary_start(&op); + + bufferlist out_bl; + int r = ioctx->operate(RBD_MIRRORING, &op, &out_bl); + if (r < 0) { + return r; + } + + bufferlist::iterator iter = out_bl.begin(); + r = mirror_image_status_get_summary_finish(&iter, states); + if (r < 0) { + return r; + } + return 0; + } + + void mirror_image_status_get_summary_start( + librados::ObjectReadOperation *op) { + bufferlist bl; + op->exec("rbd", "mirror_image_status_get_summary", bl); + } + + int mirror_image_status_get_summary_finish(bufferlist::iterator *iter, + std::map *states) { + try { + ::decode(*states, *iter); + } catch (const buffer::error &err) { + return -EBADMSG; + } + return 0; + } + + int mirror_image_status_remove_down(librados::IoCtx *ioctx) { + librados::ObjectWriteOperation op; + mirror_image_status_remove_down(&op); + return ioctx->operate(RBD_MIRRORING, &op); + } + + void mirror_image_status_remove_down(librados::ObjectWriteOperation *op) { + bufferlist bl; + op->exec("rbd", "mirror_image_status_remove_down", bl); + } + } // namespace cls_client } // namespace librbd diff --git a/src/cls/rbd/cls_rbd_client.h b/src/cls/rbd/cls_rbd_client.h index 8bc8ee2b98a73..b3dd22eb3753b 100644 --- a/src/cls/rbd/cls_rbd_client.h +++ b/src/cls/rbd/cls_rbd_client.h @@ -243,6 +243,40 @@ namespace librbd { const cls::rbd::MirrorImage &mirror_image); int mirror_image_remove(librados::IoCtx *ioctx, const std::string &image_id); + int mirror_image_status_set(librados::IoCtx *ioctx, + const std::string &global_image_id, + const cls::rbd::MirrorImageStatus &status); + void mirror_image_status_set(librados::ObjectWriteOperation *op, + const std::string &global_image_id, + const cls::rbd::MirrorImageStatus &status); + int mirror_image_status_remove(librados::IoCtx *ioctx, + const std::string &global_image_id); + void mirror_image_status_remove(librados::ObjectWriteOperation *op, + const std::string &global_image_id); + int mirror_image_status_get(librados::IoCtx *ioctx, + const std::string &global_image_id, + cls::rbd::MirrorImageStatus *status); + void mirror_image_status_get_start(librados::ObjectReadOperation *op, + const std::string &global_image_id); + int mirror_image_status_get_finish(bufferlist::iterator *iter, + cls::rbd::MirrorImageStatus *status); + int mirror_image_status_list(librados::IoCtx *ioctx, + const std::string &start, uint64_t max_return, + std::map *images, + std::map *statuses); + void mirror_image_status_list_start(librados::ObjectReadOperation *op, + const std::string &start, + uint64_t max_return); + int mirror_image_status_list_finish(bufferlist::iterator *iter, + std::map *images, + std::map *statuses); + int mirror_image_status_get_summary(librados::IoCtx *ioctx, + std::map *states); + void mirror_image_status_get_summary_start(librados::ObjectReadOperation *op); + int mirror_image_status_get_summary_finish(bufferlist::iterator *iter, + std::map *states); + int mirror_image_status_remove_down(librados::IoCtx *ioctx); + void mirror_image_status_remove_down(librados::ObjectWriteOperation *op); } // namespace cls_client } // namespace librbd diff --git a/src/cls/rbd/cls_rbd_types.cc b/src/cls/rbd/cls_rbd_types.cc index 3f68522468abc..5891e566a2a50 100644 --- a/src/cls/rbd/cls_rbd_types.cc +++ b/src/cls/rbd/cls_rbd_types.cc @@ -105,6 +105,11 @@ bool MirrorImage::operator==(const MirrorImage &rhs) const { return global_image_id == rhs.global_image_id && state == rhs.state; } +bool MirrorImage::operator<(const MirrorImage &rhs) const { + return global_image_id < rhs.global_image_id || + (global_image_id == rhs.global_image_id && state < rhs.state); +} + std::ostream& operator<<(std::ostream& os, const MirrorImageState& mirror_state) { switch (mirror_state) { case MIRROR_IMAGE_STATE_DISABLING: @@ -127,5 +132,84 @@ std::ostream& operator<<(std::ostream& os, const MirrorImage& mirror_image) { return os; } +void MirrorImageStatus::encode(bufferlist &bl) const { + ENCODE_START(1, 1, bl); + ::encode(state, bl); + ::encode(description, bl); + ::encode(last_update, bl); + ::encode(up, bl); + ENCODE_FINISH(bl); +} + +void MirrorImageStatus::decode(bufferlist::iterator &it) { + DECODE_START(1, it); + ::decode(state, it); + ::decode(description, it); + ::decode(last_update, it); + ::decode(up, it); + DECODE_FINISH(it); +} + +void MirrorImageStatus::dump(Formatter *f) const { + f->dump_string("state", state_to_string()); + f->dump_string("description", description); + f->dump_stream("last_update") << last_update; +} + +std::string MirrorImageStatus::state_to_string() const { + std::stringstream ss; + ss << (up ? "up+" : "down+") << state; + return ss.str(); +} + +void MirrorImageStatus::generate_test_instances( + std::list &o) { + o.push_back(new MirrorImageStatus()); + o.push_back(new MirrorImageStatus(MIRROR_IMAGE_STATUS_STATE_REPLAYING)); + o.push_back(new MirrorImageStatus(MIRROR_IMAGE_STATUS_STATE_ERROR, "error")); +} + +bool MirrorImageStatus::operator==(const MirrorImageStatus &rhs) const { + return state == rhs.state && description == rhs.description && up == rhs.up; +} + +std::ostream& operator<<(std::ostream& os, const MirrorImageStatusState& state) { + switch (state) { + case MIRROR_IMAGE_STATUS_STATE_UNKNOWN: + os << "unknown"; + break; + case MIRROR_IMAGE_STATUS_STATE_ERROR: + os << "error"; + break; + case MIRROR_IMAGE_STATUS_STATE_SYNCING: + os << "syncing"; + break; + case MIRROR_IMAGE_STATUS_STATE_STARTING_REPLAY: + os << "starting_replay"; + break; + case MIRROR_IMAGE_STATUS_STATE_REPLAYING: + os << "replaying"; + break; + case MIRROR_IMAGE_STATUS_STATE_STOPPING_REPLAY: + os << "stopping_replay"; + break; + case MIRROR_IMAGE_STATUS_STATE_STOPPED: + os << "stopped"; + break; + default: + os << "unknown (" << static_cast(state) << ")"; + break; + } + return os; +} + +std::ostream& operator<<(std::ostream& os, const MirrorImageStatus& status) { + os << "[" + << "state=" << status.state_to_string() << ", " + << "description=" << status.description << ", " + << "last_update=" << status.last_update << "]"; + return os; +} + } // namespace rbd } // namespace cls diff --git a/src/cls/rbd/cls_rbd_types.h b/src/cls/rbd/cls_rbd_types.h index e3189146bd980..c8780f06820d5 100644 --- a/src/cls/rbd/cls_rbd_types.h +++ b/src/cls/rbd/cls_rbd_types.h @@ -7,6 +7,7 @@ #include "include/int_types.h" #include "include/buffer.h" #include "include/encoding.h" +#include "include/utime.h" #include #include @@ -73,6 +74,7 @@ struct MirrorImage { static void generate_test_instances(std::list &o); bool operator==(const MirrorImage &rhs) const; + bool operator<(const MirrorImage &rhs) const; }; std::ostream& operator<<(std::ostream& os, const MirrorImageState& mirror_state); @@ -80,6 +82,56 @@ std::ostream& operator<<(std::ostream& os, const MirrorImage& mirror_image); WRITE_CLASS_ENCODER(MirrorImage); +enum MirrorImageStatusState { + MIRROR_IMAGE_STATUS_STATE_UNKNOWN = 0, + MIRROR_IMAGE_STATUS_STATE_ERROR = 1, + MIRROR_IMAGE_STATUS_STATE_SYNCING = 2, + MIRROR_IMAGE_STATUS_STATE_STARTING_REPLAY = 3, + MIRROR_IMAGE_STATUS_STATE_REPLAYING = 4, + MIRROR_IMAGE_STATUS_STATE_STOPPING_REPLAY = 5, + MIRROR_IMAGE_STATUS_STATE_STOPPED = 6, +}; + +inline void encode(const MirrorImageStatusState &state, bufferlist& bl, + uint64_t features=0) +{ + ::encode(static_cast(state), bl); +} + +inline void decode(MirrorImageStatusState &state, bufferlist::iterator& it) +{ + uint8_t int_state; + ::decode(int_state, it); + state = static_cast(int_state); +} + +struct MirrorImageStatus { + MirrorImageStatus() {} + MirrorImageStatus(MirrorImageStatusState state, + const std::string &description = "") + : state(state), description(description) {} + + MirrorImageStatusState state = MIRROR_IMAGE_STATUS_STATE_UNKNOWN; + std::string description; + utime_t last_update; + bool up = false; + + void encode(bufferlist &bl) const; + void decode(bufferlist::iterator &it); + void dump(Formatter *f) const; + + std::string state_to_string() const; + + static void generate_test_instances(std::list &o); + + bool operator==(const MirrorImageStatus &rhs) const; +}; + +std::ostream& operator<<(std::ostream& os, const MirrorImageStatus& status); +std::ostream& operator<<(std::ostream& os, const MirrorImageStatusState& state); + +WRITE_CLASS_ENCODER(MirrorImageStatus); + } // namespace rbd } // namespace cls -- 2.39.5