- ``ceph osd dump``
- ``ceph <tell|daemon> osd.<N> dump_blocklist``
+
+* caps: MON and MDS caps can now be used to restrict client's ability to view
+ and operate on specific Ceph file systems. The FS can be specificed using
+ ``fsname`` in caps. This also affects subcommand ``fs authorize``, the caps
+ produce by it will be specific to the FS name passed in its arguments.
If you would like the client to report the overall usage of the file system,
and not just the quota usage on the sub-directory mounted, then set the
-following config option on the client:
+following config option on the client::
-::
client quota df = false
these fields (such as openc operations with layouts).
For example, in the following snippet client.0 can modify layouts and quotas
-on the file system cephfs_a, but client.1 cannot.
-
-::
+on the file system cephfs_a, but client.1 cannot::
client.0
key: AQAz7EVWygILFRAAdIcuJ12opU/JKyfFmxhuaw==
appear after it (all flags except 'rw' must be specified in alphabetical order).
For example, in the following snippet client.0 can create or delete snapshots
-in the ``bar`` directory of file system ``cephfs_a``.
-
-::
+in the ``bar`` directory of file system ``cephfs_a``::
client.0
key: AQAz7EVWygILFRAAdIcuJ12opU/JKyfFmxhuaw==
prefix length in CIDR notation (e.g., ``10.3.0.0/16``). If present,
the use of this capability is restricted to clients connecting from
this network.
+
+File system Information Restriction
+===================================
+
+If desired, the monitor cluster can present a limited view of the file systems
+available. In this case, the monitor cluster will only inform clients about
+file systems specified by the administrator. Other file systems will not be
+reported and commands affecting them will fail as if the file systems do
+not exist.
+
+Consider following example. The Ceph cluster has 2 FSs::
+
+ $ ceph fs ls
+ name: cephfs, metadata pool: cephfs_metadata, data pools: [cephfs_data ]
+ name: cephfs2, metadata pool: cephfs2_metadata, data pools: [cephfs2_data ]
+
+But we authorize client ``someuser`` for only one FS::
+
+ $ ceph fs authorize cephfs client.someuser / rw
+ [client.someuser]
+ key = AQAmthpf89M+JhAAiHDYQkMiCq3x+J0n9e8REQ==
+ $ cat ceph.client.someuser.keyring
+ [client.someuser]
+ key = AQAmthpf89M+JhAAiHDYQkMiCq3x+J0n9e8REQ==
+ caps mds = "allow rw fsname=cephfs"
+ caps mon = "allow r fsname=cephfs"
+ caps osd = "allow rw tag cephfs data=cephfs"
+
+And the client can only see the FS that it has authorization for::
+
+ $ ceph fs ls -n client.someuser -k ceph.client.someuser.keyring
+ name: cephfs, metadata pool: cephfs_metadata, data pools: [cephfs_data ]
+
+Standby MDS daemons will always be displayed. Note that the information about
+restricted MDS daemons and file systems may become available by other means,
+such as ``ceph health detail``.
* Parse into a mds_role_t. The rank-only form is only valid
* if legacy_client_ns is set.
*/
+
+int FSMap::parse_role(
+ std::string_view role_str,
+ mds_role_t *role,
+ std::ostream &ss,
+ const std::vector<string> &filter) const
+{
+ int r = parse_role(role_str, role, ss);
+
+ string_view fs_name = get_filesystem(role->fscid)->mds_map.get_fs_name();
+
+ if (!filter.empty() &&
+ std::find(filter.begin(), filter.end(), fs_name) == filter.end()) {
+ if (r >= 0) {
+ ss << "Invalid file system";
+ }
+ return -ENOENT;
+ }
+
+ return r;
+}
+
int FSMap::parse_role(
std::string_view role_str,
mds_role_t *role,
const CompatSet &get_compat() const {return compat;}
+ void filter(const std::vector<string>& allowed)
+ {
+ if (allowed.empty()) {
+ return;
+ }
+
+ for (auto &f : filesystems) {
+ string_view fs_name = f.second->mds_map.get_fs_name();
+ if (std::find(allowed.begin(), allowed.end(), fs_name) == allowed.end()) {
+ filesystems.erase(f.first);
+ }
+ }
+
+ for (auto r : mds_roles) {
+ string_view fs_name = fs_name_from_gid(r.first);
+ if (std::find(allowed.begin(), allowed.end(), fs_name) == allowed.end()) {
+ mds_roles.erase(r.first);
+ }
+ }
+
+ legacy_client_fscid = filesystems.begin()->first;
+ }
+
void set_enable_multiple(const bool v)
{
enable_multiple = v;
/**
* Does a daemon exist with this GID?
*/
- bool gid_exists(mds_gid_t gid) const
+ bool gid_exists(mds_gid_t gid,
+ const std::vector<string>& in = {}) const
{
- return mds_roles.count(gid) > 0;
+ try {
+ string_view m = fs_name_from_gid(gid);
+ return in.empty() || std::find(in.begin(), in.end(), m) != in.end();
+ } catch (const std::out_of_range&) {
+ return false;
+ }
}
/**
return gid_exists(gid) && mds_roles.at(gid) != FS_CLUSTER_ID_NONE;
}
- fs_cluster_id_t gid_fscid(mds_gid_t gid) const
- {
+ /**
+ * Which filesystem owns this GID?
+ */
+ fs_cluster_id_t fscid_from_gid(mds_gid_t gid) const {
+ if (!gid_exists(gid)) {
+ return FS_CLUSTER_ID_NONE;
+ }
return mds_roles.at(gid);
}
/**
* Insert a new MDS daemon, as a standby
*/
- void insert(const mds_info_t& new_info);
+ void insert(const MDSMap::mds_info_t &new_info);
/**
* Assign an MDS cluster standby replay rank to a standby daemon
}
}
+ std::string_view fs_name_from_gid(mds_gid_t gid) const
+ {
+ auto fscid = mds_roles.at(gid);
+ if (fscid == FS_CLUSTER_ID_NONE or !filesystem_exists(fscid)) {
+ return std::string_view();
+ } else {
+ return get_filesystem(fscid)->mds_map.get_fs_name();
+ }
+ }
+
bool is_standby_replay(mds_gid_t who) const
{
return filesystems.at(mds_roles.at(who))->is_standby_replay(who);
Filesystem::const_ref *result
) const;
+ int parse_role(
+ std::string_view role_str,
+ mds_role_t *role,
+ std::ostream &ss,
+ const std::vector<string> &filter) const;
+
int parse_role(
std::string_view role_str,
mds_role_t *role,
int handle(
Monitor *mon,
- FSMap &fsmap,
+ FSMap& fsmap,
MonOpRequestRef op,
const cmdmap_t& cmdmap,
std::stringstream &ss) override
}
auto fs = fsmap.get_filesystem(fs_name);
- if (fs == nullptr) {
- ss << "Not found: '" << fs_name << "'";
- return -ENOENT;
- }
auto f = [](auto fs) {
fs->mds_map.set_flag(CEPH_MDSMAP_NOT_JOINABLE);
int handle(
Monitor *mon,
- FSMap &fsmap,
+ FSMap& fsmap,
MonOpRequestRef op,
const cmdmap_t& cmdmap,
std::stringstream &ss) override
int handle(
Monitor *mon,
- FSMap &fsmap,
+ FSMap& fsmap,
MonOpRequestRef op,
const cmdmap_t& cmdmap,
std::stringstream &ss) override
}
auto fs = fsmap.get_filesystem(fs_name);
- if (fs == nullptr) {
- ss << "Not found: '" << fs_name << "'";
- return -ENOENT;
- }
-
string var;
if (!cmd_getval(cmdmap, "var", var) || var.empty()) {
ss << "Invalid variable";
ss << "You must specify at least one MDS";
return -EINVAL;
}
+
if (n > 1 && n > fs->mds_map.get_max_mds()) {
if (fs->mds_map.was_snaps_ever_allowed() &&
!fs->mds_map.allows_multimds_snaps()) {
int handle(
Monitor *mon,
- FSMap &fsmap,
+ FSMap& fsmap,
MonOpRequestRef op,
const cmdmap_t& cmdmap,
std::stringstream &ss) override
return -EINVAL;
}
- auto fs = fsmap.get_filesystem(fs_name);
- if (fs == nullptr) {
- ss << "Not found: '" << fs_name << "'";
- return -ENOENT;
- }
-
int64_t poolid = mon->osdmon()->osdmap.lookup_pg_pool_name(poolname);
if (poolid < 0) {
string err;
return r;
}
+ auto fs = fsmap.get_filesystem(fs_name);
// no-op when the data_pool already on fs
if (fs->mds_map.is_data_pool(poolid)) {
ss << "data pool " << poolid << " is already on fs " << fs_name;
int handle(
Monitor *mon,
- FSMap &fsmap,
+ FSMap& fsmap,
MonOpRequestRef op,
const cmdmap_t& cmdmap,
std::stringstream &ss) override
int handle(
Monitor *mon,
- FSMap &fsmap,
+ FSMap& fsmap,
MonOpRequestRef op,
const cmdmap_t& cmdmap,
std::stringstream &ss) override
int handle(
Monitor *mon,
- FSMap &fsmap,
+ FSMap& fsmap,
MonOpRequestRef op,
const cmdmap_t& cmdmap,
std::stringstream &ss) override
int handle(
Monitor *mon,
- FSMap &fsmap,
+ FSMap& fsmap,
MonOpRequestRef op,
const cmdmap_t& cmdmap,
std::stringstream &ss) override
return -EINVAL;
}
- auto fs = fsmap.get_filesystem(fs_name);
- if (fs == nullptr) {
- ss << "Not found: '" << fs_name << "'";
- return -ENOENT;
- }
-
int64_t poolid = mon->osdmon()->osdmap.lookup_pg_pool_name(poolname);
if (poolid < 0) {
string err;
ceph_assert(poolid >= 0); // Checked by parsing code above
+ auto fs = fsmap.get_filesystem(fs_name);
if (fs->mds_map.get_first_data_pool() == poolid) {
ss << "cannot remove default data pool";
return -EINVAL;
}
-
int r = 0;
fsmap.modify_filesystem(fs->fscid,
[&r, poolid](std::shared_ptr<Filesystem> fs)
alias_prefix = new_prefix;
}
- std::string const &get_prefix() override {return alias_prefix;}
+ std::string const &get_prefix() const override {return alias_prefix;}
int handle(
Monitor *mon,
- FSMap &fsmap,
+ FSMap& fsmap,
MonOpRequestRef op,
const cmdmap_t& cmdmap,
std::stringstream &ss) override
return 0;
}
+int FileSystemCommandHandler::is_op_allowed(
+ const MonOpRequestRef& op, const FSMap& fsmap, const cmdmap_t& cmdmap,
+ std::stringstream &ss) const
+{
+ string fs_name;
+ cmd_getval(cmdmap, "fs_name", fs_name);
+
+ // so that fsmap can filtered and the original copy is untouched.
+ FSMap fsmap_copy = fsmap;
+ fsmap_copy.filter(op->get_session()->get_allowed_fs_names());
+
+ auto fs = fsmap_copy.get_filesystem(fs_name);
+ if (fs == nullptr) {
+ ss << "Filesystem not found: '" << fs_name << "'";
+ return -ENOENT;
+ }
+
+ if (!op->get_session()->fs_name_capable(fs_name, MON_CAP_W)) {
+ ss << "Permission denied: '" << fs_name << "'";
+ return -EPERM;
+ }
+
+ return 1;
+}
bool force,
std::stringstream *ss) const;
- virtual std::string const &get_prefix() {return prefix;}
+ virtual std::string const &get_prefix() const {return prefix;}
public:
FileSystemCommandHandler(const std::string &prefix_)
virtual ~FileSystemCommandHandler()
{}
- bool can_handle(std::string const &prefix_)
+ int is_op_allowed(const MonOpRequestRef& op, const FSMap& fsmap,
+ const cmdmap_t& cmdmap, std::stringstream &ss) const;
+
+ int can_handle(std::string const &prefix_, MonOpRequestRef& op, FSMap& fsmap,
+ const cmdmap_t& cmdmap, std::stringstream &ss) const
{
- return get_prefix() == prefix_;
+ if (get_prefix() != prefix_) {
+ return 0;
+ }
+
+ if (get_prefix() == "fs new" || get_prefix() == "fs flag set") {
+ return 1;
+ }
+
+ return is_op_allowed(op, fsmap, cmdmap, ss);
}
static std::list<std::shared_ptr<FileSystemCommandHandler> > load(Paxos *paxos);
using std::pair;
using std::set;
using std::string;
+using std::string_view;
using std::stringstream;
using std::to_string;
using std::vector;
bufferlist rdata;
stringstream ss, ds;
- const auto &fsmap = get_fsmap();
-
cmdmap_t cmdmap;
if (!cmdmap_from_json(m->cmd, &cmdmap, ss)) {
// ss has reason for failure
return true;
}
+ // to use const qualifier filter fsmap beforehand
+ FSMap _fsmap_copy = get_fsmap();
+ _fsmap_copy.filter(session->get_allowed_fs_names());
+ const auto& fsmap = _fsmap_copy;
+
if (prefix == "mds stat") {
if (f) {
f->open_object_section("mds_stat");
bool batched_propose = false;
for (const auto &h : handlers) {
- if (h->can_handle(prefix)) {
- batched_propose = h->batched_propose();
- if (batched_propose) {
- paxos->plug();
- }
- r = h->handle(mon, pending, op, cmdmap, ss);
- if (batched_propose) {
- paxos->unplug();
- }
+ r = h->can_handle(prefix, op, pending, cmdmap, ss);
+ if (r == 1) {
+ ; // pass, since we got the right handler.
+ } else if (r == 0) {
+ continue;
+ } else {
+ goto out;
+ }
- if (r == -EAGAIN) {
- // message has been enqueued for retry; return.
- dout(4) << __func__ << " enqueue for retry by prepare_command" << dendl;
- return false;
- } else {
- if (r == 0) {
- // On successful updates, print the updated map
- print_map(pending);
- }
- // Successful or not, we're done: respond.
- goto out;
+ batched_propose = h->batched_propose();
+ if (batched_propose) {
+ paxos->plug();
+ }
+ r = h->handle(mon, pending, op, cmdmap, ss);
+ if (batched_propose) {
+ paxos->unplug();
+ }
+
+ if (r == -EAGAIN) {
+ // message has been enqueued for retry; return.
+ dout(4) << __func__ << " enqueue for retry by prepare_command" << dendl;
+ return false;
+ } else {
+ if (r == 0) {
+ // On successful updates, print the updated map
+ print_map(pending);
}
+ // Successful or not, we're done: respond.
+ goto out;
}
}
<< cmd_vartype_stringify(cmdmap.at("state")) << "'";
return -EINVAL;
}
- if (fsmap.gid_exists(gid)) {
+ if (fsmap.gid_exists(gid, op->get_session()->get_allowed_fs_names())) {
fsmap.modify_daemon(gid, [state](auto& info) {
info.state = state;
});
cmd_getval(cmdmap, "role_or_gid", who);
MDSMap::mds_info_t failed_info;
+ mds_gid_t gid = gid_from_arg(fsmap, who, ss);
+ if (gid == MDS_GID_NONE) {
+ return -EINVAL;
+ }
+ if(!fsmap.gid_exists(gid, op->get_session()->get_allowed_fs_names())) {
+ ss << "MDS named '" << who << "' does not exist, is not up or you "
+ << "lack the permission to see.";
+ return -EINVAL;
+ }
+ string_view fs_name = fsmap.fs_name_from_gid(gid);
+ if (!op->get_session()->fs_name_capable(fs_name, MON_CAP_W)) {
+ ss << "Permission denied.";
+ return -EPERM;
+ }
+
r = fail_mds(fsmap, ss, who, &failed_info);
if (r < 0 && r == -EAGAIN) {
mon->osdmon()->wait_for_writeable(op, new C_RetryMessage(this, op));
<< cmd_vartype_stringify(cmdmap.at("gid")) << "'";
return -EINVAL;
}
- if (!fsmap.gid_exists(gid)) {
+ if (!fsmap.gid_exists(gid, op->get_session()->get_allowed_fs_names())) {
ss << "mds gid " << gid << " does not exist";
- r = 0;
+ return 0;
+ }
+ string_view fs_name = fsmap.fs_name_from_gid(gid);
+ if (!op->get_session()->fs_name_capable(fs_name, MON_CAP_W)) {
+ ss << "Permission denied.";
+ return -EPERM;
+ }
+ const auto &info = fsmap.get_info_gid(gid);
+ MDSMap::DaemonState state = info.state;
+ if (state > 0) {
+ ss << "cannot remove active mds." << info.name
+ << " rank " << info.rank;
+ return -EBUSY;
} else {
- const auto &info = fsmap.get_info_gid(gid);
- MDSMap::DaemonState state = info.state;
- if (state > 0) {
- ss << "cannot remove active mds." << info.name
- << " rank " << info.rank;
- return -EBUSY;
- } else {
- fsmap.erase(gid, {});
- ss << "removed mds gid " << gid;
- return 0;
- }
+ fsmap.erase(gid, {});
+ ss << "removed mds gid " << gid;
+ return 0;
}
} else if (prefix == "mds rmfailed") {
bool confirm = false;
std::string role_str;
cmd_getval(cmdmap, "role", role_str);
mds_role_t role;
- int r = fsmap.parse_role(role_str, &role, ss);
+ const auto fs_names = op->get_session()->get_allowed_fs_names();
+ int r = fsmap.parse_role(role_str, &role, ss, fs_names);
if (r < 0) {
ss << "invalid role '" << role_str << "'";
return -EINVAL;
}
+ string_view fs_name = fsmap.get_filesystem(role.fscid)->mds_map.get_fs_name();
+ if (!op->get_session()->fs_name_capable(fs_name, MON_CAP_W)) {
+ ss << "Permission denied.";
+ return -EPERM;
+ }
fsmap.modify_filesystem(
role.fscid,
std::string role_str;
cmd_getval(cmdmap, "role", role_str);
mds_role_t role;
- r = fsmap.parse_role(role_str, &role, ss);
+ const auto fs_names = op->get_session()->get_allowed_fs_names();
+ r = fsmap.parse_role(role_str, &role, ss, fs_names);
if (r < 0) {
return r;
}
+ string_view fs_name = fsmap.get_filesystem(role.fscid)->mds_map.get_fs_name();
+ if (!op->get_session()->fs_name_capable(fs_name, MON_CAP_W)) {
+ ss << "Permission denied.";
+ return -EPERM;
+ }
bool modified = fsmap.undamaged(role.fscid, role.rank);
if (modified) {
return -EINVAL;
}
+ string_view fs_name = fsmap.fs_name_from_gid(gid);
+ if (!op->get_session()->fs_name_capable(fs_name, MON_CAP_W)) {
+ ss << "Permission denied.";
+ return -EPERM;
+ }
+
bool freeze = false;
{
std::string str;
{
dout(20) << __func__ << ": " << sub->type << dendl;
- const auto &fsmap = get_fsmap();
+ // to use const qualifier filter fsmap beforehand
+ FSMap _fsmap_copy = get_fsmap();
+ _fsmap_copy.filter(sub->session->get_allowed_fs_names());
+ const auto& fsmap = _fsmap_copy;
if (sub->type == "fsmap") {
if (sub->next <= fsmap.get_epoch()) {
auto info = fsmap.get_info_gid(gid);
const mds_info_t* rep_info = nullptr;
if (info.rank >= 0) {
- auto fscid = fsmap.gid_fscid(gid);
+ auto fscid = fsmap.fscid_from_gid(gid);
rep_info = fsmap.find_replacement_for({fscid, info.rank});
}
bool dropped = drop_mds(fsmap, gid, rep_info, propose_osdmap);
bool prepare_offload_targets(MonOpRequestRef op);
int fail_mds(FSMap &fsmap, std::ostream &ss,
- const std::string &arg,
- mds_info_t *failed_info);
+ const std::string &arg, mds_info_t *failed_info);
bool preprocess_command(MonOpRequestRef op);
bool prepare_command(MonOpRequestRef op);
(std::string, command)
(kvmap, command_args)
(mon_rwxa_t, allow)
- (std::string, network))
+ (std::string, network)
+ (std::string, fs_name))
BOOST_FUSION_ADAPT_STRUCT(StringConstraint,
(StringConstraint::MatchType, match_type)
unquoted_word %= +char_("a-zA-Z0-9_./-");
str %= quoted_string | unquoted_word;
network_str %= +char_("/.:a-fA-F0-9][");
+ fs_name_str %= +char_("a-zA-Z0-9-_.");
spaces = +(lit(' ') | lit('\n') | lit('\t'));
>> qi::attr(string()) >> qi::attr(string()) >> qi::attr(string())
>> qi::attr(map<string,StringConstraint>())
>> rwxa
- >> -(spaces >> lit("network") >> spaces >> network_str);
+ >> -(spaces >> lit("network") >> spaces >> network_str)
+ >> -(spaces >> lit("fsname") >> (lit('=') | spaces) >> fs_name_str);
// rwxa := * | [r][w][x]
rwxa =
qi::rule<Iterator, string()> quoted_string;
qi::rule<Iterator, string()> unquoted_word;
qi::rule<Iterator, string()> str, network_str;
+ qi::rule<Iterator, string()> fs_name_str;
qi::rule<Iterator, StringConstraint()> str_match, str_prefix, str_regex;
qi::rule<Iterator, pair<string, StringConstraint>()> kv_pair;
#include "include/common_fwd.h"
#include "include/types.h"
#include "common/entity_name.h"
+#include "mds/mdstypes.h"
static const __u8 MON_CAP_R = (1 << 1); // read
static const __u8 MON_CAP_W = (1 << 2); // write
struct MonCapGrant {
/*
- * A grant can come in one of four forms:
+ * A grant can come in one of five forms:
*
* - a blanket allow ('allow rw', 'allow *')
* - this will match against any service and the read/write/exec flags
* of key/value pairs that constrain use of that command. if no pairs
* are specified, any arguments are allowed; if a pair is specified, that
* argument must be present and equal or match a prefix.
+ *
+ * - an fs name ('allow fsname foo')
+ * - this will restrict access to MDSMaps in the FSMap to the provided
+ * fs name.
*/
std::string service;
std::string profile;
std::string command;
std::map<std::string, StringConstraint> command_args;
+ std::string fs_name;
// restrict by network
std::string network;
MonCapGrant(std::string c, std::string a, StringConstraint co) : command(std::move(c)) {
command_args[a] = co;
}
+ MonCapGrant(mon_rwxa_t a, std::string fsname) : fs_name(fsname), allow(a) {}
/**
* check if given request parameters match our constraints
allow == MON_CAP_ANY &&
service.length() == 0 &&
profile.length() == 0 &&
- command.length() == 0;
+ command.length() == 0 &&
+ fs_name.empty();
}
};
void decode(ceph::buffer::list::const_iterator& bl);
void dump(ceph::Formatter *f) const;
static void generate_test_instances(std::list<MonCap*>& ls);
+
+ std::vector<string> allowed_fs_names() const {
+ std::vector<string> ret;
+ for (auto& g : grants) {
+ if (not g.fs_name.empty()) {
+ ret.push_back(g.fs_name);
+ } else {
+ return {};
+ }
+ }
+ return ret;
+ }
+
+ bool fs_name_capable(string_view fs_name, __u8 mask) {
+ for (auto& g: grants) {
+ if (g.is_allow_all()) {
+ return true;
+ }
+ if (g.fs_name.empty() || g.fs_name == fs_name) {
+ if (mask & g.allow) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
};
WRITE_CLASS_ENCODER(MonCap)
}
}
-void Monitor::get_cluster_status(stringstream &ss, Formatter *f)
+void Monitor::get_cluster_status(stringstream &ss, Formatter *f,
+ MonSession *session)
{
if (f)
f->open_object_section("status");
+ const auto&& fs_names = session->get_allowed_fs_names();
+
mono_clock::time_point now = mono_clock::now();
if (f) {
f->dump_stream("fsid") << monmap->get_fsid();
mgrstatmon()->print_summary(f, NULL);
f->close_section();
f->open_object_section("fsmap");
- mdsmon()->get_fsmap().print_summary(f, NULL);
+
+ FSMap fsmap_copy = mdsmon()->get_fsmap();
+ if (!fs_names.empty()) {
+ fsmap_copy.filter(fs_names);
+ }
+ const FSMap *fsmapp = &fsmap_copy;
+
+ fsmapp->print_summary(f, NULL);
f->close_section();
f->open_object_section("mgrmap");
mgrmon()->get_map().print_summary(f, nullptr);
mgrmon()->get_map().print_summary(nullptr, &ss);
ss << "\n";
}
- if (mdsmon()->should_print_status()) {
- ss << " mds: " << spacing << mdsmon()->get_fsmap() << "\n";
+
+ FSMap fsmap_copy = mdsmon()->get_fsmap();
+ if (!fs_names.empty()) {
+ fsmap_copy.filter(fs_names);
+ }
+ const FSMap *fsmapp = &fsmap_copy;
+
+ if (fsmapp->filesystem_count() > 0 and mdsmon()->should_print_status()){
+ ss << " mds: " << spacing << *fsmapp << "\n";
}
+
ss << " osd: " << spacing;
osdmon()->osdmap.print_summary(NULL, ss, string(maxlen + 6, ' '));
ss << "\n";
if (prefix == "status") {
// get_cluster_status handles f == NULL
- get_cluster_status(ds, f.get());
+ get_cluster_status(ds, f.get(), session);
if (f) {
f->flush(ds);
public:
- void get_cluster_status(std::stringstream &ss, ceph::Formatter *f);
+ void get_cluster_status(std::stringstream &ss, ceph::Formatter *f,
+ MonSession *session);
void reply_command(MonOpRequestRef op, int rc, const std::string &rs, version_t version);
void reply_command(MonOpRequestRef op, int rc, const std::string &rs, ceph::buffer::list& rdata, version_t version);
get_peer_socket_addr());
}
+ std::vector<string> get_allowed_fs_names() const {
+ return caps.allowed_fs_names();
+ }
+
+ bool fs_name_capable(string_view fsname, __u8 mask) {
+ return caps.fs_name_capable(fsname, mask);
+ }
+
const entity_addr_t& get_peer_socket_addr() {
return socket_addr;
}