From d0570e33fc0049160253c0e70073498faea55ab6 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 19 Mar 2021 08:21:18 -0400 Subject: [PATCH] mgr/ServiceMap: adjust 'ceph -s' summary - Do not list individual daemon ids as this won't scale for larger clusters - Do not contemplate multile daemons of the same type that register with different "daemon_type" -- not until we actually have any that do that. - Present counts by various groupings: distinct hosts and rgw zones to start. services: mon: 1 daemons, quorum a (age 4m) mgr: x(active, since 3m) osd: 1 osds: 1 up (since 3m), 1 in (since 3m) cephfs-mirror: 1 daemon active (1 hosts) rbd-mirror: 2 daemons active (1 hosts) rgw: 2 daemons active (1 hosts, 1 zones) Signed-off-by: Sage Weil (cherry picked from commit ab0d8f2ae9f551e15a4c7bacbf69161e91263785) --- src/mgr/ServiceMap.cc | 76 +++++++++++++++--------------------- src/test/librados/service.cc | 16 +++++--- 2 files changed, 42 insertions(+), 50 deletions(-) diff --git a/src/mgr/ServiceMap.cc b/src/mgr/ServiceMap.cc index 4babb81f224c0..b6f8ad97c86d1 100644 --- a/src/mgr/ServiceMap.cc +++ b/src/mgr/ServiceMap.cc @@ -78,60 +78,48 @@ std::string ServiceMap::Service::get_summary() const return "no daemons active"; } - std::ostringstream ss; - - // The format two pairs in metadata: - // "daemon_type" : "${TYPE}" - // "daemon_prefix" : "${PREFIX}" + // If "daemon_type" is present, this will be used in place of "daemon" when + // reporting the count (e.g., "${N} daemons"). // - // TYPE: will be used to replace the default "daemon(s)" - // showed in `ceph -s`. If absent, the "daemon" will be used. - // PREFIX: if present the active members will be classified - // by the prefix instead of "daemon_name". + // We will additional break down the count by various groupings, based + // on the following keys: + // + // "hostname" -> host(s) + // "zone_id" -> zone(s) // - // For exmaple for iscsi gateways, it will be something likes: - // "daemon_type" : "portal" - // "daemon_prefix" : "gateway${N}" // The `ceph -s` will be something likes: - // iscsi: 3 portals active (gateway0, gateway1, gateway2) + // iscsi: 3 portals active (3 hosts) + // rgw: 3 gateways active (3 hosts, 1 zone) - std::map> prefs; + std::map> groupings; + std::string type("daemon"); + int num = 0; for (auto& d : daemons) { - // In case the "daemon_type" is absent, use the - // default "daemon" type - std::string type("daemon"); - std::string prefix; - - auto t = d.second.metadata.find("daemon_type"); - if (t != d.second.metadata.end()) { - type = d.second.metadata.at("daemon_type"); + ++num; + if (auto p = d.second.metadata.find("daemon_type"); + p != d.second.metadata.end()) { + type = p->second; } - auto p = d.second.metadata.find("daemon_prefix"); - if (p != d.second.metadata.end()) { - prefix = d.second.metadata.at("daemon_prefix"); - } else { - // In case the "daemon_prefix" is absent, show - // the daemon_name instead. - prefix = d.first; + for (auto k : {make_pair("zone", "zone_id"), + make_pair("host", "hostname")}) { + auto p = d.second.metadata.find(k.second); + if (p != d.second.metadata.end()) { + groupings[k.first].insert(p->second); + } } - auto& pref = prefs[type]; - pref.insert(prefix); } - for (auto &pr : prefs) { - if (!ss.str().empty()) - ss << ", "; - - ss << pr.second.size() << " " << pr.first - << (pr.second.size() > 1 ? "s" : "") - << " active"; - - if (pr.second.size()) { - ss << " ("; - std::copy(std::begin(pr.second), std::end(pr.second), - std::experimental::make_ostream_joiner(ss, ", ")); - ss << ")"; + std::ostringstream ss; + ss << num << " " << type << (num > 1 ? "s" : "") << " active"; + if (groupings.size()) { + ss << " ("; + for (auto i = groupings.begin(); i != groupings.end(); ++i) { + if (i != groupings.begin()) { + ss << ", "; + } + ss << i->second.size() << " " << i->first << (i->second.size() ? "s" : ""); } + ss << ")"; } return ss.str(); diff --git a/src/test/librados/service.cc b/src/test/librados/service.cc index 9611b40eb1107..bc8e26efaf4d8 100644 --- a/src/test/librados/service.cc +++ b/src/test/librados/service.cc @@ -71,12 +71,16 @@ static void status_format_func(const int i, std::mutex &lock, "daemon_prefix", '\0', "gateway", '\0')); } else { string prefix = string("gw") + stringify(i % 4); - ASSERT_NE(-1, asprintf(&metadata_buf, "%s%c%s%c%s%c%s%c", + string zone = string("z") + stringify(i % 3); + ASSERT_NE(-1, asprintf(&metadata_buf, "%s%c%s%c%s%c%s%c%s%c%s%c%s%c%s%c", "daemon_type", '\0', "portal", '\0', - "daemon_prefix", '\0', prefix.c_str(), '\0')); + "daemon_prefix", '\0', prefix.c_str(), '\0', + "hostname", '\0', prefix.c_str(), '\0', + "zone_id", '\0', zone.c_str(), '\0' + )); } string name = string("rbd/image") + stringify(i); - ASSERT_EQ(0, rados_service_register(cluster, "iscsi", name.c_str(), + ASSERT_EQ(0, rados_service_register(cluster, "foo", name.c_str(), metadata_buf)); std::unique_lock l(lock); @@ -140,10 +144,10 @@ TEST(LibRadosService, StatusFormat) { ASSERT_EQ(0, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, &outbuf, &outlen, NULL, NULL)); std::string out(outbuf, outlen); + cout << out << std::endl; bool success = false; - auto r1 = out.find("5 portals active (gw0, gw1, gw2, gw3, rbd/image1)"); - auto r2 = out.find("2 daemons active (gateway, rbd/image0"); - if (std::string::npos != r1 && std::string::npos != r2) { + auto r1 = out.find("16 portals active (1 hosts, 3 zones)"); + if (std::string::npos != r1) { success = true; } rados_buffer_free(outbuf); -- 2.39.5