From b27820cc7388c074e2fc3778399d1f0a8da58a84 Mon Sep 17 00:00:00 2001 From: Jason Dillaman Date: Mon, 2 Dec 2019 15:02:49 -0500 Subject: [PATCH] rbd: incorporate rbd-mirror daemon status in mirror pool status This will ensure that the Ceph dashbord's block mirroring page and the CLI's 'mirror pool status' have matching health indications. Fixes: https://tracker.ceph.com/issues/42748 Signed-off-by: Jason Dillaman --- qa/workunits/rbd/rbd_mirror_stress.sh | 2 +- src/tools/rbd/MirrorDaemonServiceInfo.cc | 365 +++++++++++++++-------- src/tools/rbd/MirrorDaemonServiceInfo.h | 56 +++- src/tools/rbd/action/MirrorImage.cc | 9 +- src/tools/rbd/action/MirrorPool.cc | 143 ++++++--- 5 files changed, 413 insertions(+), 162 deletions(-) diff --git a/qa/workunits/rbd/rbd_mirror_stress.sh b/qa/workunits/rbd/rbd_mirror_stress.sh index a1d7d03470a61..7788863ffef2e 100755 --- a/qa/workunits/rbd/rbd_mirror_stress.sh +++ b/qa/workunits/rbd/rbd_mirror_stress.sh @@ -77,7 +77,7 @@ wait_for_pool_healthy() for s in `seq 1 40`; do test $s -ne 1 && sleep 30 - state=$(rbd --cluster ${cluster} -p ${pool} mirror pool status | grep 'health:' | cut -d' ' -f 2) + state=$(rbd --cluster ${cluster} -p ${pool} mirror pool status | grep 'image health:' | cut -d' ' -f 3) test "${state}" = "ERROR" && break test "${state}" = "OK" && return 0 done diff --git a/src/tools/rbd/MirrorDaemonServiceInfo.cc b/src/tools/rbd/MirrorDaemonServiceInfo.cc index bdacc62c25de3..e7422e66a4d36 100644 --- a/src/tools/rbd/MirrorDaemonServiceInfo.cc +++ b/src/tools/rbd/MirrorDaemonServiceInfo.cc @@ -14,162 +14,293 @@ namespace rbd { +std::ostream& operator<<(std::ostream& os, MirrorHealth mirror_health) { + switch (mirror_health) { + case MIRROR_HEALTH_OK: + os << "OK"; + break; + case MIRROR_HEALTH_UNKNOWN: + os << "UNKNOWN"; + break; + case MIRROR_HEALTH_WARNING: + os << "WARNING"; + break; + case MIRROR_HEALTH_ERROR: + os << "ERROR"; + break; + } + return os; +} + +std::string MirrorService::get_image_description() const { + std::string description = (!client_id.empty() ? client_id : + stringify(service_id)); + if (!hostname.empty()) { + description += " on " + hostname; + } + return description; +} + +void MirrorService::dump_image( + argument_types::Format::Formatter formatter) const { + formatter->open_object_section("daemon_service"); + formatter->dump_string("service_id", service_id); + formatter->dump_string("instance_id", instance_id); + formatter->dump_string("daemon_id", client_id); + formatter->dump_string("hostname", hostname); + formatter->close_section(); +} + int MirrorDaemonServiceInfo::init() { + int r = get_mirror_service_dump(); + if (r < 0) { + return r; + } else if (m_mirror_services.empty()) { + return 0; + } + + r = get_mirror_service_status(); + if (r < 0) { + return r; + } + + return 0; +} + +const MirrorService* MirrorDaemonServiceInfo::get_by_service_id( + const std::string& service_id) const { + auto it = m_mirror_services.find(service_id); + if (it == m_mirror_services.end()) { + return nullptr; + } - std::string cmd = "{\"prefix\": \"service dump\"}"; + return &it->second; +} + +const MirrorService* MirrorDaemonServiceInfo::get_by_instance_id( + const std::string& instance_id) const { + auto it = m_instance_to_service_ids.find(instance_id); + if (it == m_instance_to_service_ids.end()) { + return nullptr; + } + return get_by_service_id(it->second); +} + +MirrorServices MirrorDaemonServiceInfo::get_mirror_services() const { + MirrorServices mirror_services; + for (auto& it : m_mirror_services) { + mirror_services.push_back(it.second); + } + return mirror_services; +} + +int MirrorDaemonServiceInfo::get_mirror_service_dump() { + librados::Rados rados(m_io_ctx); + std::string cmd = R"({"prefix": "service dump", "format": "json"})"; bufferlist in_bl; bufferlist out_bl; - int r = librados::Rados(m_io_ctx).mgr_command(cmd, in_bl, &out_bl, nullptr); + + int r = rados.mon_command(cmd, in_bl, &out_bl, nullptr); if (r < 0) { - std::cerr << "rbd: failed to get service dump: " << cpp_strerror(r) + std::cerr << "rbd: failed to query services: " << cpp_strerror(r) << std::endl; return r; } - bool json_valid = false; json_spirit::mValue json_root; - if (json_spirit::read(out_bl.to_str(), json_root)) { - try { - auto& json_obj = json_root.get_obj(); - if (json_obj.count("services")) { - auto &services = json_obj["services"].get_obj(); - if (services.count("rbd-mirror")) { - auto &mirror_service = services["rbd-mirror"].get_obj(); - if (mirror_service.count("daemons")) { - for (auto &it : mirror_service["daemons"].get_obj()) { - if (it.second.type() != json_spirit::obj_type || - !it.second.get_obj().count("metadata")) { - continue; - } - auto &service_id = it.first; - auto &daemon_metadata = it.second.get_obj()["metadata"].get_obj(); - for (auto &iter : daemon_metadata) { - if (iter.second.type() != json_spirit::str_type) { - continue; - } - m_daemons_metadata[service_id][iter.first] = iter.second.get_str(); - } - } - } - } + if(!json_spirit::read(out_bl.to_str(), json_root)) { + std::cerr << "rbd: invalid service dump JSON received" << std::endl; + return -EBADMSG; + } + + try { + auto& services = json_root.get_obj()["services"]; + if (services.is_null()) { + std::cerr << "rbd: missing services in service dump JSON" << std::endl; + return -EBADMSG; + } + + auto& service = services.get_obj()["rbd-mirror"]; + if (service.is_null()) { + // no rbd-mirror daemons running + return 0; + } + + auto& daemons = service.get_obj()["daemons"]; + if (daemons.is_null()) { + return 0; + } + + for (auto& daemon_pair : daemons.get_obj()) { + // rbd-mirror instances will always be integers but other objects + // are included + auto& service_id = daemon_pair.first; + if (daemon_pair.second.type() != json_spirit::obj_type) { + continue; + } + + auto& daemon = daemon_pair.second.get_obj(); + auto& metadata_val = daemon["metadata"]; + if (metadata_val.is_null()) { + continue; + } + auto& metadata = metadata_val.get_obj(); + + MirrorService mirror_service{service_id}; + + auto& client_id = metadata["id"]; + if (!client_id.is_null()) { + mirror_service.client_id = client_id.get_str(); } - json_valid = true; - } catch (std::runtime_error&) { + + auto& ceph_version = metadata["ceph_version_short"]; + if (!ceph_version.is_null()) { + mirror_service.ceph_version = ceph_version.get_str(); + } + + auto& hostname = metadata["hostname"]; + if (!hostname.is_null()) { + mirror_service.hostname = hostname.get_str(); + } + + m_mirror_services[service_id] = mirror_service; } - } - if (!json_valid) { - std::cerr << "rbd: failed to parse service status" << std::endl; + } catch (std::runtime_error&) { + std::cerr << "rbd: unexpected service dump JSON received" << std::endl; return -EBADMSG; } - cmd = "{\"prefix\": \"service status\"}"; + return 0; +} + +int MirrorDaemonServiceInfo::get_mirror_service_status() { + librados::Rados rados(m_io_ctx); + std::string cmd = R"({"prefix": "service status", "format": "json"})"; + bufferlist in_bl; + bufferlist out_bl; - out_bl.clear(); - r = librados::Rados(m_io_ctx).mgr_command(cmd, in_bl, &out_bl, nullptr); + int r = rados.mon_command(cmd, in_bl, &out_bl, nullptr); if (r < 0) { - std::cerr << "rbd: failed to get service status: " << cpp_strerror(r) + std::cerr << "rbd: failed to query service status: " << cpp_strerror(r) << std::endl; return r; } + json_spirit::mValue json_root; + if(!json_spirit::read(out_bl.to_str(), json_root)) { + std::cerr << "rbd: invalid service status JSON received" << std::endl; + return -EBADMSG; + } - json_valid = false; - if (json_spirit::read(out_bl.to_str(), json_root)) { - try { - auto& json_obj = json_root.get_obj(); - if (json_obj.count("rbd-mirror")) { - auto &mirror_service = json_obj["rbd-mirror"].get_obj(); - for (auto &it : mirror_service) { - auto &service_id = it.first; - auto &daemon = it.second.get_obj(); - if (daemon.count("status") && - daemon["status"].get_obj().count("json")) { - auto& status_json_str = - daemon["status"].get_obj()["json"].get_str(); - json_spirit::mValue status_json_root; - if (json_spirit::read(status_json_str, status_json_root)) { - auto& status = status_json_root.get_obj(); - auto iter = status.find(stringify(m_io_ctx.get_id())); - if (iter != status.end() && - iter->second.get_obj().count("instance_id")) { - auto &instance_id = - iter->second.get_obj()["instance_id"].get_str(); - m_instance_id_to_service_id[instance_id] = service_id; - } - } - } - } - } - json_valid = true; - } catch (std::runtime_error&) { + bool found_leader = false; + bool found_pool = false; + + try { + auto& service = json_root.get_obj()["rbd-mirror"]; + if (service.is_null()) { + return 0; } - } - if (!json_valid) { - std::cerr << "rbd: failed to parse service status" << std::endl; - return -EBADMSG; - } + for (auto& daemon_pair : service.get_obj()) { + std::string service_id = daemon_pair.first; + auto it = m_mirror_services.find(service_id); + if (it == m_mirror_services.end()) { + continue; + } - return 0; -} + auto& mirror_service = it->second; + auto& daemon = daemon_pair.second.get_obj(); + auto& status = daemon["status"]; + if (status.is_null()) { + mirror_service.callouts.push_back("not reporting status"); + mirror_service.health = MIRROR_HEALTH_WARNING; + continue; + } -std::string MirrorDaemonServiceInfo::get_description( - const std::string &instance_id) const { - if (!m_instance_id_to_service_id.count(instance_id)) { - return {}; - } + auto& json = status.get_obj()["json"]; + if (json.is_null()) { + mirror_service.callouts.push_back("not reporting status"); + mirror_service.health = MIRROR_HEALTH_WARNING; + continue; + } - auto service_id = m_instance_id_to_service_id.find(instance_id)->second; + json_spirit::mValue json_status; + if(!json_spirit::read(json.get_str(), json_status)) { + std::cerr << "rbd: invalid service status daemon status JSON received" + << std::endl; + return -EBADMSG; + } - auto it = m_daemons_metadata.find(service_id); - if (it == m_daemons_metadata.end()) { - return service_id; - } + auto& pool_val = json_status.get_obj()[stringify(m_io_ctx.get_id())]; + if (pool_val.is_null()) { + mirror_service.callouts.push_back("not reporting status for pool"); + mirror_service.health = MIRROR_HEALTH_WARNING; + continue; + } - auto &metadata = it->second; - auto iter = metadata.find("id"); - std::string description = (iter != metadata.end()) ? - iter->second : service_id; - iter = metadata.find("hostname"); - if (iter != metadata.end()) { - description += " on " + iter->second; - } + auto& pool = pool_val.get_obj(); + found_pool = true; - return description; -} + auto& instance_id = pool["instance_id"]; + if (!instance_id.is_null()) { + mirror_service.instance_id = instance_id.get_str(); + m_instance_to_service_ids[mirror_service.instance_id] = service_id; + } -void MirrorDaemonServiceInfo::dump( - const std::string &instance_id, - argument_types::Format::Formatter formatter) const { - formatter->open_object_section("daemon_service"); - BOOST_SCOPE_EXIT(formatter) { - formatter->close_section(); - } BOOST_SCOPE_EXIT_END; + auto& leader = pool["leader"]; + if (!leader.is_null() && leader.get_bool()) { + mirror_service.leader = true; + found_leader = true; + } - if (instance_id.empty() || - !m_instance_id_to_service_id.count(instance_id)) { - return; - } + MirrorHealth mirror_service_health = MIRROR_HEALTH_OK; + auto& callouts = pool["callouts"]; + if (!callouts.is_null()) { + for (auto& callout_pair : callouts.get_obj()) { + auto& callout = callout_pair.second.get_obj(); + auto& level = callout["level"]; + if (level.is_null()) { + continue; + } - auto service_id = m_instance_id_to_service_id.find(instance_id)->second; - formatter->dump_string("service_id", service_id); - formatter->dump_string("instance_id", instance_id); + auto& level_str = level.get_str(); + if (mirror_service_health < MIRROR_HEALTH_ERROR && + level_str == "error") { + mirror_service_health = MIRROR_HEALTH_ERROR; + } else if (mirror_service_health < MIRROR_HEALTH_WARNING && + level_str == "warning") { + mirror_service_health = MIRROR_HEALTH_WARNING; + } - auto it = m_daemons_metadata.find(service_id); - if (it == m_daemons_metadata.end()) { - return; + auto& text = callout["text"]; + if (!text.is_null()) { + mirror_service.callouts.push_back(text.get_str()); + } + } + } + mirror_service.health = mirror_service_health; + } + } catch (std::runtime_error&) { + std::cerr << "rbd: unexpected service status JSON received" << std::endl; + return -EBADMSG; } - auto &metadata = it->second; - auto iter = metadata.find("id"); - if (iter != metadata.end()) { - formatter->dump_string("daemon_id", iter->second); + // compute overall daemon health + m_daemon_health = MIRROR_HEALTH_OK; + if (!found_pool) { + // no daemons are reporting status for this pool + m_daemon_health = MIRROR_HEALTH_ERROR; + } else if (!found_leader) { + // no daemons are reporting leader role for this pool + m_daemon_health = MIRROR_HEALTH_WARNING; } - iter = metadata.find("hostname"); - if (iter != metadata.end()) { - formatter->dump_string("hostname", iter->second); + + for (auto& pair : m_mirror_services) { + m_daemon_health = std::max(m_daemon_health, pair.second.health); } + + return 0; } } // namespace rbd diff --git a/src/tools/rbd/MirrorDaemonServiceInfo.h b/src/tools/rbd/MirrorDaemonServiceInfo.h index 7c3c38568477f..d667332e5131d 100644 --- a/src/tools/rbd/MirrorDaemonServiceInfo.h +++ b/src/tools/rbd/MirrorDaemonServiceInfo.h @@ -7,11 +7,44 @@ #include "include/rados/librados_fwd.hpp" #include "tools/rbd/ArgumentTypes.h" -#include +#include +#include #include +#include namespace rbd { +enum MirrorHealth { + MIRROR_HEALTH_OK = 0, + MIRROR_HEALTH_UNKNOWN = 1, + MIRROR_HEALTH_WARNING = 2, + MIRROR_HEALTH_ERROR = 3 +}; + +std::ostream& operator<<(std::ostream& os, MirrorHealth mirror_health); + +struct MirrorService { + MirrorService() {} + explicit MirrorService(const std::string& service_id) + : service_id(service_id) { + } + + std::string service_id; + std::string instance_id; + bool leader = false; + std::string client_id; + std::string ceph_version; + std::string hostname; + std::list callouts; + + MirrorHealth health = MIRROR_HEALTH_UNKNOWN; + + std::string get_image_description() const; + void dump_image(argument_types::Format::Formatter formatter) const; +}; + +typedef std::list MirrorServices; + class MirrorDaemonServiceInfo { public: MirrorDaemonServiceInfo(librados::IoCtx &io_ctx) : m_io_ctx(io_ctx) { @@ -19,14 +52,25 @@ public: int init(); - std::string get_description(const std::string &instance_id) const; - void dump(const std::string &instance_id, - argument_types::Format::Formatter formatter) const; + const MirrorService* get_by_service_id(const std::string& service_id) const; + const MirrorService* get_by_instance_id(const std::string& instance_id) const; + + MirrorServices get_mirror_services() const; + MirrorHealth get_daemon_health() const { + return m_daemon_health; + } private: librados::IoCtx &m_io_ctx; - std::map m_instance_id_to_service_id; - std::map> m_daemons_metadata; + + std::map m_mirror_services; + std::map m_instance_to_service_ids; + + MirrorHealth m_daemon_health = MIRROR_HEALTH_UNKNOWN; + + int get_mirror_service_dump(); + int get_mirror_service_status(); + }; } // namespace rbd diff --git a/src/tools/rbd/action/MirrorImage.cc b/src/tools/rbd/action/MirrorImage.cc index ff079a2adbabc..bd77742750db5 100644 --- a/src/tools/rbd/action/MirrorImage.cc +++ b/src/tools/rbd/action/MirrorImage.cc @@ -320,6 +320,7 @@ int execute_status(const po::variables_map &vm, } } + auto mirror_service = daemon_service_info.get_by_instance_id(instance_id); if (formatter != nullptr) { formatter->open_object_section("image"); formatter->dump_string("name", image_name); @@ -328,7 +329,9 @@ int execute_status(const po::variables_map &vm, formatter->dump_string("state", utils::mirror_image_site_status_state( local_status)); formatter->dump_string("description", local_status.description); - daemon_service_info.dump(instance_id, formatter); + if (mirror_service != nullptr) { + mirror_service->dump_image(formatter); + } formatter->dump_string("last_update", utils::timestr( local_status.last_update)); } @@ -360,9 +363,9 @@ int execute_status(const po::variables_map &vm, std::cout << " state: " << utils::mirror_image_site_status_state( local_status) << "\n" << " description: " << local_status.description << "\n"; - if (!instance_id.empty()) { + if (mirror_service != nullptr) { std::cout << " service: " << - daemon_service_info.get_description(instance_id) << "\n"; + mirror_service->get_image_description() << "\n"; } std::cout << " last_update: " << utils::timestr( local_status.last_update) << std::endl; diff --git a/src/tools/rbd/action/MirrorPool.cc b/src/tools/rbd/action/MirrorPool.cc index 457f528122a35..1c974fe17f1ed 100644 --- a/src/tools/rbd/action/MirrorPool.cc +++ b/src/tools/rbd/action/MirrorPool.cc @@ -5,6 +5,7 @@ #include "tools/rbd/MirrorDaemonServiceInfo.h" #include "tools/rbd/Shell.h" #include "tools/rbd/Utils.h" +#include "include/buffer.h" #include "include/Context.h" #include "include/stringify.h" #include "include/rbd/librbd.hpp" @@ -637,6 +638,7 @@ protected: m_instance_ids.count(m_image_id)) ? m_instance_ids.find(m_image_id)->second : ""; + auto mirror_service = m_daemon_service_info.get_by_instance_id(instance_id); if (m_formatter != nullptr) { m_formatter->open_object_section("image"); m_formatter->dump_string("name", m_mirror_image_global_status.name); @@ -646,7 +648,9 @@ protected: m_formatter->dump_string("state", utils::mirror_image_site_status_state( local_status)); m_formatter->dump_string("description", local_status.description); - m_daemon_service_info.dump(instance_id, m_formatter); + if (mirror_service != nullptr) { + mirror_service->dump_image(m_formatter); + } m_formatter->dump_string("last_update", utils::timestr( local_status.last_update)); } @@ -679,9 +683,9 @@ protected: std::cout << " state: " << utils::mirror_image_site_status_state( local_status) << std::endl << " description: " << local_status.description << std::endl; - if (!instance_id.empty()) { + if (mirror_service != nullptr) { std::cout << " service: " << - m_daemon_service_info.get_description(instance_id) << std::endl; + mirror_service->get_image_description() << std::endl; } std::cout << " last_update: " << utils::timestr( local_status.last_update) << std::endl; @@ -777,6 +781,36 @@ private: }; +int get_mirror_image_status( + librados::IoCtx& io_ctx, uint32_t* total_images, + std::map* mirror_image_states, + MirrorHealth* mirror_image_health) { + librbd::RBD rbd; + int r = rbd.mirror_image_status_summary(io_ctx, mirror_image_states); + if (r < 0) { + std::cerr << "rbd: failed to get status summary for mirrored images: " + << cpp_strerror(r) << std::endl; + return r; + } + + *mirror_image_health = MIRROR_HEALTH_OK; + for (auto &it : *mirror_image_states) { + auto &state = it.first; + if (*mirror_image_health < MIRROR_HEALTH_WARNING && + (state != MIRROR_IMAGE_STATUS_STATE_REPLAYING && + state != MIRROR_IMAGE_STATUS_STATE_STOPPED)) { + *mirror_image_health = MIRROR_HEALTH_WARNING; + } + if (*mirror_image_health < MIRROR_HEALTH_ERROR && + state == MIRROR_IMAGE_STATUS_STATE_ERROR) { + *mirror_image_health = MIRROR_HEALTH_ERROR; + } + *total_images += it.second; + } + + return 0; +} + } // anonymous namespace void get_peer_bootstrap_create_arguments(po::options_description *positional, @@ -1414,50 +1448,45 @@ int execute_status(const po::variables_map &vm, librbd::RBD rbd; - std::map states; - r = rbd.mirror_image_status_summary(io_ctx, &states); + uint32_t total_images = 0; + std::map mirror_image_states; + MirrorHealth mirror_image_health = MIRROR_HEALTH_UNKNOWN; + r = get_mirror_image_status(io_ctx, &total_images, &mirror_image_states, + &mirror_image_health); if (r < 0) { - std::cerr << "rbd: failed to get status summary for mirrored images: " - << cpp_strerror(r) << std::endl; return r; } - if (formatter != nullptr) { - formatter->open_object_section("status"); + MirrorDaemonServiceInfo daemon_service_info(io_ctx); + r = daemon_service_info.init(); + if (r < 0) { + return r; } - enum Health {Ok = 0, Warning = 1, Error = 2} health = Ok; - const char *names[] = {"OK", "WARNING", "ERROR"}; - int total = 0; + MirrorHealth mirror_daemon_health = daemon_service_info.get_daemon_health(); + auto mirror_services = daemon_service_info.get_mirror_services(); - for (auto &it : states) { - auto &state = it.first; - if (health < Warning && - (state != MIRROR_IMAGE_STATUS_STATE_REPLAYING && - state != MIRROR_IMAGE_STATUS_STATE_STOPPED)) { - health = Warning; - } - if (health < Error && - state == MIRROR_IMAGE_STATUS_STATE_ERROR) { - health = Error; - } - total += it.second; - } + auto mirror_health = std::max(mirror_image_health, mirror_daemon_health); if (formatter != nullptr) { + formatter->open_object_section("status"); formatter->open_object_section("summary"); - formatter->dump_string("health", names[health]); + formatter->dump_stream("health") << mirror_health; + formatter->dump_stream("daemon_health") << mirror_daemon_health; + formatter->dump_stream("image_health") << mirror_image_health; formatter->open_object_section("states"); - for (auto &it : states) { + for (auto &it : mirror_image_states) { std::string state_name = utils::mirror_image_status_state(it.first); formatter->dump_int(state_name.c_str(), it.second); } formatter->close_section(); // states formatter->close_section(); // summary } else { - std::cout << "health: " << names[health] << std::endl; - std::cout << "images: " << total << " total" << std::endl; - for (auto &it : states) { + std::cout << "health: " << mirror_health << std::endl; + std::cout << "daemon health: " << mirror_daemon_health << std::endl; + std::cout << "image health: " << mirror_image_health << std::endl; + std::cout << "images: " << total_images << " total" << std::endl; + for (auto &it : mirror_image_states) { std::cout << " " << it.second << " " << utils::mirror_image_status_state(it.first) << std::endl; } @@ -1466,6 +1495,53 @@ int execute_status(const po::variables_map &vm, int ret = 0; if (verbose) { + // dump per-daemon status + if (formatter != nullptr) { + formatter->open_array_section("daemons"); + for (auto& mirror_service : mirror_services) { + formatter->open_object_section("daemon"); + formatter->dump_string("service_id", mirror_service.service_id); + formatter->dump_string("instance_id", mirror_service.instance_id); + formatter->dump_string("client_id", mirror_service.client_id); + formatter->dump_string("hostname", mirror_service.hostname); + formatter->dump_string("ceph_version", mirror_service.ceph_version); + formatter->dump_bool("leader", mirror_service.leader); + formatter->dump_stream("health") << mirror_service.health; + if (!mirror_service.callouts.empty()) { + formatter->open_array_section("callouts"); + for (auto& callout : mirror_service.callouts) { + formatter->dump_string("callout", callout); + } + formatter->close_section(); // callouts + } + formatter->close_section(); // daemon + } + formatter->close_section(); // daemons + } else { + std::cout << std::endl << "DAEMONS" << std::endl; + if (mirror_services.empty()) { + std::cout << " none" << std::endl; + } + for (auto& mirror_service : mirror_services) { + std::cout << "service " << mirror_service.service_id << ":" + << std::endl + << " instance_id: " << mirror_service.instance_id + << std::endl + << " client_id: " << mirror_service.client_id << std::endl + << " hostname: " << mirror_service.hostname << std::endl + << " version: " << mirror_service.ceph_version << std::endl + << " leader: " << (mirror_service.leader ? "true" : "false") + << std::endl + << " health: " << mirror_service.health << std::endl; + if (!mirror_service.callouts.empty()) { + std::cout << " callouts: " << mirror_service.callouts << std::endl; + } + std::cout << std::endl; + } + std::cout << std::endl; + } + + // dump per-image status std::vector mirror_peers; utils::get_mirror_peer_sites(io_ctx, &mirror_peers); @@ -1474,10 +1550,11 @@ int execute_status(const po::variables_map &vm, if (formatter != nullptr) { formatter->open_array_section("images"); + } else { + std::cout << "IMAGES"; } std::map instance_ids; - MirrorDaemonServiceInfo daemon_service_info(io_ctx); std::string start_image_id; while (true) { @@ -1501,10 +1578,6 @@ int execute_status(const po::variables_map &vm, start_image_id = ids.rbegin()->first; } - if (!instance_ids.empty()) { - daemon_service_info.init(); - } - ImageRequestGenerator generator( io_ctx, instance_ids, mirror_peers, peer_fsid_to_name, daemon_service_info, formatter); -- 2.39.5