From: Leonid Chernin Date: Tue, 10 Feb 2026 06:50:51 +0000 (+0200) Subject: nvmeofgw: introduce nvme-gw show-all X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=ca090f3a35909d1a7c238f531445b5f5c9650109;p=ceph.git nvmeofgw: introduce nvme-gw show-all Introduce a new read-only command, nvme-gw show-all, which iterates over all configured pools and groups and runs nvme-gw show for each, simplifying gateway inspection. fixes https://tracker.ceph.com/issues/74854 Signed-off-by: Leonid Chernin --- diff --git a/src/mon/MonCommands.h b/src/mon/MonCommands.h index 825005e087d..639eb6f34ec 100644 --- a/src/mon/MonCommands.h +++ b/src/mon/MonCommands.h @@ -1452,6 +1452,10 @@ COMMAND("nvme-gw show" " show nvmeof gateways within (pool, group)", "mon", "r") +COMMAND("nvme-gw show-all", + " Dump nvmeof gateways for all pools and groups", + "mon", "r") + COMMAND("nvme-gw listeners" " name=pool,type=CephString" " name=group,type=CephString", diff --git a/src/mon/NVMeofGwMon.cc b/src/mon/NVMeofGwMon.cc index fe8bf32318b..62295d54eb6 100644 --- a/src/mon/NVMeofGwMon.cc +++ b/src/mon/NVMeofGwMon.cc @@ -440,6 +440,97 @@ bool NVMeofGwMon::prepare_update(MonOpRequestRef op) } } +bool NVMeofGwMon::nvme_gw_show_command(ceph::Formatter* f, bufferlist &rdata, const std::string &pool, + const std::string &group) { + auto group_key = std::make_pair(pool, group); + std::stringstream sstrm (""); + dout(10) << "nvme-gw show pool " << pool << " group " << group << dendl; + + f->open_object_section("common"); + f->dump_unsigned("epoch", map.epoch); + f->dump_string("pool", pool); + f->dump_string("group", group); + if (HAVE_FEATURE(mon.get_quorum_con_features(), NVMEOFHA)) { + f->dump_string("features", "LB"); + if (map.created_gws[group_key].size()) { + time_t seconds_since_1970 = time(NULL); + uint32_t index = ((seconds_since_1970/60) % + map.created_gws[group_key].size()); + auto it = map.created_gws[group_key].begin(); + std::advance(it, index); + f->dump_unsigned("rebalance_ana_group", it->second.ana_grp_id + 1); + } + } + f->dump_unsigned("num gws", map.created_gws[group_key].size()); + if (map.gw_epoch.find(group_key) != map.gw_epoch.end()) + f->dump_unsigned("GW-epoch", map.gw_epoch[group_key]); + if (map.created_gws[group_key].size() != 0) { + sstrm << "[ "; + NvmeGwId gw_id; + BeaconSubsystems *subsystems = NULL; + for (auto& gw_created_pair: map.created_gws[group_key]) { + gw_id = gw_created_pair.first; + auto& st = gw_created_pair.second; + if (st.availability != gw_availability_t::GW_DELETING) { + // not show ana group of deleting gw in the list - + // it is information for the GW used in rebalancing process + sstrm << st.ana_grp_id+1 << " "; + } + if (st.availability == gw_availability_t::GW_AVAILABLE) { + subsystems = &st.subsystems; + } + } + sstrm << "]"; + f->dump_string("Anagrp list", sstrm.str()); + std::map num_ns; + uint16_t total_ns = 0; + if (subsystems && subsystems->size()) { + for (auto & subs_it:*subsystems) { + for (auto & ns :subs_it.namespaces) { + if (num_ns.find(ns.anagrpid) == num_ns.end()) num_ns[ns.anagrpid] = 0; + num_ns[ns.anagrpid] +=1; + total_ns += 1; + } + } + } + f->dump_unsigned("num-namespaces", total_ns); + f->open_array_section("Created Gateways:"); + uint32_t i = 0; + for (auto& gw_created_pair: map.created_gws[group_key]) { + auto& gw_id = gw_created_pair.first; + auto& state = gw_created_pair.second; + i = 0; + f->open_object_section("stat"); + f->dump_string("gw-id", gw_id); + f->dump_unsigned("anagrp-id",state.ana_grp_id+1); + f->dump_unsigned("num-namespaces", num_ns[state.ana_grp_id+1]); + f->dump_unsigned("performed-full-startup", state.performed_full_startup); + std::stringstream sstrm1; + sstrm1 << state.availability; + f->dump_string("Availability", sstrm1.str()); + uint32_t num_listeners = 0; + if (state.availability == gw_availability_t::GW_AVAILABLE) { + for (auto &subs: state.subsystems) { + num_listeners += subs.listeners.size(); + } + f->dump_unsigned("num-listeners", num_listeners); + } + sstrm1.str(""); + for (auto &state_itr: map.created_gws[group_key][gw_id].sm_state) { + sstrm1 << " " << state_itr.first + 1 << ": " + << state.sm_state[state_itr.first]; + if (++i < map.created_gws[group_key][gw_id].sm_state.size()) + sstrm1<< ", "; + } + f->dump_string("ana states", sstrm1.str()); + f->close_section(); + } + f->close_section(); + } + f->close_section(); + return true; +} + bool NVMeofGwMon::preprocess_command(MonOpRequestRef op) { dout(10) << dendl; @@ -463,127 +554,33 @@ bool NVMeofGwMon::preprocess_command(MonOpRequestRef op) dout(10) << "MonCommand : "<< prefix << dendl; string format = cmd_getval_or(cmdmap, "format", "plain"); boost::scoped_ptr f(Formatter::create(format)); - if (prefix == "nvme-gw show") { - std::string pool, group; - if (!f) { - f.reset(Formatter::create(format, "json-pretty", "json-pretty")); + if (!f) { + f.reset(Formatter::create(format, "json-pretty", "json-pretty")); + } + if (prefix == "nvme-gw show-all") { + f->open_array_section("gateways"); + for (auto &[group_key, gws_states]:map.created_gws) { + nvme_gw_show_command(f.get(), rdata, group_key.first, group_key.second); } + f->close_section(); // gateways + + f->flush(rdata); + sstrm.str(""); + getline(sstrm, rs); + mon.reply_command(op, err, rs, rdata, get_last_committed()); + return true; + } else if (prefix == "nvme-gw show") { + std::string pool, group; cmd_getval(cmdmap, "pool", pool); cmd_getval(cmdmap, "group", group); - auto group_key = std::make_pair(pool, group); - dout(10) << "nvme-gw show pool " << pool << " group " << group << dendl; - - f->open_object_section("common"); - f->dump_unsigned("epoch", map.epoch); - f->dump_string("pool", pool); - f->dump_string("group", group); - f->dump_bool("beacon_diff_enabled", - map.published_features & NVMeofGwMap::FLAG_BEACONDIFF); - if (HAVE_FEATURE(mon.get_quorum_con_features(), NVMEOFHA)) { - f->dump_string("features", "LB"); - if (map.created_gws[group_key].size()) { - time_t seconds_since_1970 = time(NULL); - uint32_t index = ((seconds_since_1970/60) % - map.created_gws[group_key].size()); - auto it = map.created_gws[group_key].begin(); - std::advance(it, index); - f->dump_unsigned("rebalance_ana_group", it->second.ana_grp_id + 1); - } - } - f->dump_unsigned("num gws", map.created_gws[group_key].size()); - if (map.gw_epoch.find(group_key) != map.gw_epoch.end()) - f->dump_unsigned("GW-epoch", map.gw_epoch[group_key]); - if (map.created_gws[group_key].size() == 0) { - f->close_section(); - f->flush(rdata); - sstrm.str(""); - } else { - sstrm << "[ "; - NvmeGwId gw_id; - BeaconSubsystems *subsystems = NULL; - for (auto& gw_created_pair: map.created_gws[group_key]) { - gw_id = gw_created_pair.first; - auto& st = gw_created_pair.second; - if (st.availability != gw_availability_t::GW_DELETING) { - // not show ana group of deleting gw in the list - - // it is information for the GW used in rebalancing process - sstrm << st.ana_grp_id+1 << " "; - } - if (st.availability == gw_availability_t::GW_AVAILABLE) { - subsystems = &st.subsystems; - } - } - sstrm << "]"; - f->dump_string("Anagrp list", sstrm.str()); - std::map num_ns; - uint16_t total_ns = 0; - if (subsystems && subsystems->size()) { - for (auto & subs_it:*subsystems) { - for (auto & ns :subs_it.namespaces) { - if (num_ns.find(ns.anagrpid) == num_ns.end()) num_ns[ns.anagrpid] = 0; - num_ns[ns.anagrpid] +=1; - total_ns += 1; - } - } - } - f->dump_unsigned("num-namespaces", total_ns); - f->open_array_section("Created Gateways:"); - uint32_t i = 0; - for (auto& gw_created_pair: map.created_gws[group_key]) { - auto& gw_id = gw_created_pair.first; - auto& state = gw_created_pair.second; - i = 0; - f->open_object_section("stat"); - f->dump_string("gw-id", gw_id); - f->dump_unsigned("anagrp-id",state.ana_grp_id+1); - f->dump_string("location", state.location); - bool cleanup_in_process; - bool is_disaster = map.is_location_in_disaster - (group_key, state.location, cleanup_in_process); - if (is_disaster) { - std::string disaster_state = (cleanup_in_process) ? "Disaster-cleanup": - "Disaster"; - f->dump_string("disaster state", disaster_state); - } - std::string admin_state = (state.gw_admin_state == - gw_admin_state_t::GW_ADMIN_ENABLED) ? "ENABLED" : "DISABLED"; - f->dump_string("admin state", admin_state); - f->dump_unsigned("num-namespaces", num_ns[state.ana_grp_id+1]); - f->dump_unsigned("performed-full-startup", state.performed_full_startup); - std::stringstream sstrm1; - sstrm1 << state.availability; - f->dump_string("Availability", sstrm1.str()); - uint32_t num_listeners = 0; - if ((state.availability == gw_availability_t::GW_AVAILABLE) || - (state.availability == gw_availability_t::GW_CREATED)) { - for (auto &subs: state.subsystems) { - num_listeners += subs.listeners.size(); - } - f->dump_unsigned("num-listeners", num_listeners); - } - sstrm1.str(""); - for (auto &state_itr: map.created_gws[group_key][gw_id].sm_state) { - sstrm1 << " " << state_itr.first + 1 << ": " - << state.sm_state[state_itr.first]; - if (++i < map.created_gws[group_key][gw_id].sm_state.size()) - sstrm1<< ", "; - } - f->dump_string("ana states", sstrm1.str()); - f->close_section(); - } - f->close_section(); - f->close_section(); - f->flush(rdata); - sstrm.str(""); - } + nvme_gw_show_command(f.get(), rdata, pool, group); + f->flush(rdata); + sstrm.str(""); getline(sstrm, rs); mon.reply_command(op, err, rs, rdata, get_last_committed()); return true; } else if (prefix == "nvme-gw listeners") { std::string pool, group; - if (!f) { - f.reset(Formatter::create(format, "json-pretty", "json-pretty")); - } cmd_getval(cmdmap, "pool", pool); cmd_getval(cmdmap, "group", group); auto group_key = std::make_pair(pool, group); diff --git a/src/mon/NVMeofGwMon.h b/src/mon/NVMeofGwMon.h index 17f92ab2bfe..5e13687f78d 100644 --- a/src/mon/NVMeofGwMon.h +++ b/src/mon/NVMeofGwMon.h @@ -74,6 +74,9 @@ public: bool prepare_update(MonOpRequestRef op) override; bool preprocess_command(MonOpRequestRef op); + bool nvme_gw_show_command(ceph::Formatter* f, + bufferlist &rdata, const std::string &pool, + const std::string &group); bool prepare_command(MonOpRequestRef op); void encode_full(MonitorDBStore::TransactionRef t) override {}