mirror of
https://github.com/ceph/ceph
synced 2025-02-21 01:47:25 +00:00
tools: monmaptool: support monmap features
Adds three new options: --feature-list will list monmap features, as well as available features. --feature-set sets a feature on the monmap --feature-unset unsets a feature on the monmap Signed-off-by: Joao Eduardo Luis <joao@suse.de>
This commit is contained in:
parent
acf4b8604c
commit
f0e29abe4c
@ -11,7 +11,12 @@
|
||||
$ monmaptool --add foo 3.4.5.6:7890 mymonmap
|
||||
monmaptool: monmap file mymonmap
|
||||
monmaptool: map already contains mon.foo
|
||||
usage: [--print] [--create [--clobber][--fsid uuid]] [--generate] [--set-initial-members] [--add name 1.2.3.4:567] [--rm name] <mapfilename>
|
||||
usage: [--print] [--create [--clobber][--fsid uuid]]
|
||||
[--generate] [--set-initial-members]
|
||||
[--add name 1.2.3.4:567] [--rm name]
|
||||
[--feature-list [plain|parseable]]
|
||||
[--feature-set <value> [--optional|--persistent]]
|
||||
[--feature-unset <value> [--optional|--persistent]] <mapfilename>
|
||||
[1]
|
||||
|
||||
$ monmaptool --print mymonmap
|
||||
|
91
src/test/cli/monmaptool/feature-set-unset-list.t
Normal file
91
src/test/cli/monmaptool/feature-set-unset-list.t
Normal file
@ -0,0 +1,91 @@
|
||||
$ monmaptool --create --add a 10.10.10.10:1234 /tmp/test.monmap.1234
|
||||
monmaptool: monmap file /tmp/test.monmap.1234
|
||||
monmaptool: generated fsid [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (re)
|
||||
monmaptool: writing epoch 0 to /tmp/test.monmap.1234 (1 monitors)
|
||||
|
||||
$ monmaptool --feature-list --feature-list plain --feature-list parseable /tmp/test.monmap.1234
|
||||
monmaptool: monmap file /tmp/test.monmap.1234
|
||||
MONMAP FEATURES:
|
||||
persistent: [none]
|
||||
optional: [none]
|
||||
required: [none]
|
||||
|
||||
AVAILABLE FEATURES:
|
||||
supported: [kraken(1)]
|
||||
persistent: [kraken(1)]
|
||||
MONMAP FEATURES:
|
||||
persistent: [none]
|
||||
optional: [none]
|
||||
required: [none]
|
||||
|
||||
AVAILABLE FEATURES:
|
||||
supported: [kraken(1)]
|
||||
persistent: [kraken(1)]
|
||||
monmap:persistent:[none]
|
||||
monmap:optional:[none]
|
||||
monmap:required:[none]
|
||||
available:supported:[kraken(1)]
|
||||
available:persistent:[kraken(1)]
|
||||
|
||||
$ monmaptool --feature-set foo /tmp/test.monmap.1234
|
||||
unknown features name 'foo' or unable to parse value: Expected option value to be integer, got 'foo'
|
||||
usage: [--print] [--create [--clobber][--fsid uuid]]
|
||||
[--generate] [--set-initial-members]
|
||||
[--add name 1.2.3.4:567] [--rm name]
|
||||
[--feature-list [plain|parseable]]
|
||||
[--feature-set <value> [--optional|--persistent]]
|
||||
[--feature-unset <value> [--optional|--persistent]] <mapfilename>
|
||||
[1]
|
||||
|
||||
$ monmaptool --feature-set kraken --feature-set 16 --optional --feature-set 32 --persistent /tmp/test.monmap.1234
|
||||
monmaptool: monmap file /tmp/test.monmap.1234
|
||||
monmaptool: writing epoch 0 to /tmp/test.monmap.1234 (1 monitors)
|
||||
|
||||
$ monmaptool --feature-list /tmp/test.monmap.1234
|
||||
monmaptool: monmap file /tmp/test.monmap.1234
|
||||
MONMAP FEATURES:
|
||||
persistent: [kraken(1),unknown(32)]
|
||||
optional: [unknown(16)]
|
||||
required: [kraken(1),unknown(16),unknown(32)]
|
||||
|
||||
AVAILABLE FEATURES:
|
||||
supported: [kraken(1)]
|
||||
persistent: [kraken(1)]
|
||||
|
||||
$ monmaptool --feature-unset 32 --optional --feature-list /tmp/test.monmap.1234
|
||||
monmaptool: monmap file /tmp/test.monmap.1234
|
||||
MONMAP FEATURES:
|
||||
persistent: [kraken(1),unknown(32)]
|
||||
optional: [unknown(16)]
|
||||
required: [kraken(1),unknown(16),unknown(32)]
|
||||
|
||||
AVAILABLE FEATURES:
|
||||
supported: [kraken(1)]
|
||||
persistent: [kraken(1)]
|
||||
monmaptool: writing epoch 0 to /tmp/test.monmap.1234 (1 monitors)
|
||||
|
||||
$ monmaptool --feature-unset 32 --persistent --feature-unset 16 --optional --feature-list /tmp/test.monmap.1234
|
||||
monmaptool: monmap file /tmp/test.monmap.1234
|
||||
MONMAP FEATURES:
|
||||
persistent: [kraken(1)]
|
||||
optional: [none]
|
||||
required: [kraken(1)]
|
||||
|
||||
AVAILABLE FEATURES:
|
||||
supported: [kraken(1)]
|
||||
persistent: [kraken(1)]
|
||||
monmaptool: writing epoch 0 to /tmp/test.monmap.1234 (1 monitors)
|
||||
|
||||
$ monmaptool --feature-unset kraken --feature-list /tmp/test.monmap.1234
|
||||
monmaptool: monmap file /tmp/test.monmap.1234
|
||||
MONMAP FEATURES:
|
||||
persistent: [none]
|
||||
optional: [none]
|
||||
required: [none]
|
||||
|
||||
AVAILABLE FEATURES:
|
||||
supported: [kraken(1)]
|
||||
persistent: [kraken(1)]
|
||||
monmaptool: writing epoch 0 to /tmp/test.monmap.1234 (1 monitors)
|
||||
|
||||
$ rm /tmp/test.monmap.1234
|
@ -1,3 +1,8 @@
|
||||
$ monmaptool --help
|
||||
usage: [--print] [--create [--clobber][--fsid uuid]] [--generate] [--set-initial-members] [--add name 1.2.3.4:567] [--rm name] <mapfilename>
|
||||
usage: [--print] [--create [--clobber][--fsid uuid]]
|
||||
[--generate] [--set-initial-members]
|
||||
[--add name 1.2.3.4:567] [--rm name]
|
||||
[--feature-list [plain|parseable]]
|
||||
[--feature-set <value> [--optional|--persistent]]
|
||||
[--feature-unset <value> [--optional|--persistent]] <mapfilename>
|
||||
[1]
|
||||
|
@ -9,7 +9,12 @@
|
||||
monmaptool: monmap file mymonmap
|
||||
monmaptool: removing doesnotexist
|
||||
monmaptool: map does not contain doesnotexist
|
||||
usage: [--print] [--create [--clobber][--fsid uuid]] [--generate] [--set-initial-members] [--add name 1.2.3.4:567] [--rm name] <mapfilename>
|
||||
usage: [--print] [--create [--clobber][--fsid uuid]]
|
||||
[--generate] [--set-initial-members]
|
||||
[--add name 1.2.3.4:567] [--rm name]
|
||||
[--feature-list [plain|parseable]]
|
||||
[--feature-set <value> [--optional|--persistent]]
|
||||
[--feature-unset <value> [--optional|--persistent]] <mapfilename>
|
||||
[1]
|
||||
|
||||
$ monmaptool --print mymonmap
|
||||
|
@ -1,4 +1,9 @@
|
||||
$ monmaptool
|
||||
monmaptool: must specify monmap filename
|
||||
usage: [--print] [--create [--clobber][--fsid uuid]] [--generate] [--set-initial-members] [--add name 1.2.3.4:567] [--rm name] <mapfilename>
|
||||
usage: [--print] [--create [--clobber][--fsid uuid]]
|
||||
[--generate] [--set-initial-members]
|
||||
[--add name 1.2.3.4:567] [--rm name]
|
||||
[--feature-list [plain|parseable]]
|
||||
[--feature-set <value> [--optional|--persistent]]
|
||||
[--feature-unset <value> [--optional|--persistent]] <mapfilename>
|
||||
[1]
|
||||
|
@ -24,10 +24,146 @@ using namespace std;
|
||||
|
||||
void usage()
|
||||
{
|
||||
cout << " usage: [--print] [--create [--clobber][--fsid uuid]] [--generate] [--set-initial-members] [--add name 1.2.3.4:567] [--rm name] <mapfilename>" << std::endl;
|
||||
cout << " usage: [--print] [--create [--clobber][--fsid uuid]]\n"
|
||||
<< " [--generate] [--set-initial-members]\n"
|
||||
<< " [--add name 1.2.3.4:567] [--rm name]\n"
|
||||
<< " [--feature-list [plain|parseable]]\n"
|
||||
<< " [--feature-set <value> [--optional|--persistent]]\n"
|
||||
<< " [--feature-unset <value> [--optional|--persistent]] "
|
||||
<< "<mapfilename>"
|
||||
<< std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
struct feature_op_t {
|
||||
enum type_t {
|
||||
PERSISTENT,
|
||||
OPTIONAL,
|
||||
PLAIN,
|
||||
PARSEABLE,
|
||||
NONE
|
||||
};
|
||||
|
||||
enum op_t {
|
||||
OP_SET,
|
||||
OP_UNSET,
|
||||
OP_LIST
|
||||
};
|
||||
|
||||
op_t op;
|
||||
type_t type;
|
||||
mon_feature_t feature;
|
||||
|
||||
feature_op_t() : op(OP_LIST), type(NONE) { }
|
||||
// default to 'persistent' feature if not specified
|
||||
feature_op_t(op_t o) : op(o), type(PERSISTENT) { }
|
||||
feature_op_t(op_t o, type_t t) : op(o), type(t) { }
|
||||
feature_op_t(op_t o, type_t t, mon_feature_t &f) :
|
||||
op(o), type(t), feature(t) { }
|
||||
|
||||
void set_optional() {
|
||||
type = OPTIONAL;
|
||||
}
|
||||
void set_persistent() {
|
||||
type = PERSISTENT;
|
||||
}
|
||||
bool parse_value(string &s, ostream *errout = NULL) {
|
||||
|
||||
feature = ceph::features::mon::get_feature_by_name(s);
|
||||
if (feature != ceph::features::mon::FEATURE_NONE) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// try parsing as numerical value
|
||||
uint64_t feature_val;
|
||||
string interr;
|
||||
feature_val = strict_strtoll(s.c_str(), 10, &interr);
|
||||
if (!interr.empty()) {
|
||||
if (errout) {
|
||||
*errout << "unknown features name '" << s
|
||||
<< "' or unable to parse value: " << interr << std::endl;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
feature = mon_feature_t(feature_val);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
void features_list(feature_op_t &f, MonMap &m)
|
||||
{
|
||||
if (f.type == feature_op_t::type_t::PLAIN) {
|
||||
|
||||
cout << "MONMAP FEATURES:" << std::endl;
|
||||
cout << " persistent: ";
|
||||
m.persistent_features.print_with_value(cout);
|
||||
cout << std::endl;
|
||||
cout << " optional: ";
|
||||
m.optional_features.print_with_value(cout);
|
||||
cout << std::endl;
|
||||
cout << " required: ";
|
||||
m.get_required_features().print_with_value(cout);
|
||||
cout << std::endl;
|
||||
|
||||
cout << std::endl;
|
||||
cout << "AVAILABLE FEATURES:" << std::endl;
|
||||
cout << " supported: ";
|
||||
ceph::features::mon::get_supported().print_with_value(cout);
|
||||
cout << std::endl;
|
||||
cout << " persistent: ";
|
||||
ceph::features::mon::get_persistent().print_with_value(cout);
|
||||
cout << std::endl;
|
||||
} else if (f.type == feature_op_t::type_t::PARSEABLE) {
|
||||
|
||||
cout << "monmap:persistent:";
|
||||
m.persistent_features.print_with_value(cout);
|
||||
cout << std::endl;
|
||||
cout << "monmap:optional:";
|
||||
m.optional_features.print_with_value(cout);
|
||||
cout << std::endl;
|
||||
cout << "monmap:required:";
|
||||
m.get_required_features().print_with_value(cout);
|
||||
cout << std::endl;
|
||||
cout << "available:supported:";
|
||||
ceph::features::mon::get_supported().print_with_value(cout);
|
||||
cout << std::endl;
|
||||
cout << "available:persistent:";
|
||||
ceph::features::mon::get_persistent().print_with_value(cout);
|
||||
cout << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
bool handle_features(list<feature_op_t>& lst, MonMap &m)
|
||||
{
|
||||
if (lst.empty())
|
||||
return false;
|
||||
|
||||
bool modified = false;
|
||||
|
||||
for (auto &f : lst) {
|
||||
if (f.op == feature_op_t::op_t::OP_LIST) {
|
||||
features_list(f, m);
|
||||
} else if (f.op == feature_op_t::op_t::OP_SET ||
|
||||
f.op == feature_op_t::op_t::OP_UNSET) {
|
||||
|
||||
modified = true;
|
||||
|
||||
mon_feature_t &target =
|
||||
( f.type == feature_op_t::type_t::OPTIONAL ?
|
||||
m.optional_features : m.persistent_features );
|
||||
|
||||
if (f.op == feature_op_t::op_t::OP_SET) {
|
||||
target.set_feature(f.feature);
|
||||
} else {
|
||||
target.unset_feature(f.feature);
|
||||
}
|
||||
} else {
|
||||
cerr << "unknow feature operation type '" << f.op << "'" << std::endl;
|
||||
}
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
vector<const char*> args;
|
||||
@ -40,10 +176,12 @@ int main(int argc, const char **argv)
|
||||
bool create = false;
|
||||
bool clobber = false;
|
||||
bool modified = false;
|
||||
bool show_features = false;
|
||||
bool generate = false;
|
||||
bool filter = false;
|
||||
map<string,entity_addr_t> add;
|
||||
list<string> rm;
|
||||
list<feature_op_t> features;
|
||||
|
||||
global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY,
|
||||
CINIT_FLAG_NO_DEFAULT_CONFIG_FILE);
|
||||
@ -82,6 +220,53 @@ int main(int argc, const char **argv)
|
||||
} else if (ceph_argparse_witharg(args, i, &val, "--rm", (char*)NULL)) {
|
||||
rm.push_back(val);
|
||||
modified = true;
|
||||
} else if (ceph_argparse_flag(args, i, "--feature-list", (char*)NULL)) {
|
||||
string format = *i;
|
||||
if (format == "plain" || format == "parseable") {
|
||||
i = args.erase(i);
|
||||
} else {
|
||||
format = "plain";
|
||||
}
|
||||
|
||||
feature_op_t f(feature_op_t::op_t::OP_LIST,
|
||||
feature_op_t::type_t::PLAIN);
|
||||
|
||||
if (format == "parseable") {
|
||||
f.type = feature_op_t::type_t::PARSEABLE;
|
||||
} else if (format != "plain") {
|
||||
cerr << "invalid format type for list: '" << val << "'" << std::endl;
|
||||
usage();
|
||||
}
|
||||
|
||||
features.push_back(f);
|
||||
show_features = true;
|
||||
} else if (ceph_argparse_witharg(args, i, &val,
|
||||
"--feature-set", (char*)NULL)) {
|
||||
// parse value
|
||||
feature_op_t f(feature_op_t::op_t::OP_SET);
|
||||
if (!f.parse_value(val, &cerr)) {
|
||||
usage();
|
||||
}
|
||||
features.push_back(f);
|
||||
|
||||
} else if (ceph_argparse_witharg(args, i, &val,
|
||||
"--feature-unset", (char*)NULL)) {
|
||||
// parse value
|
||||
feature_op_t f(feature_op_t::op_t::OP_UNSET);
|
||||
if (!f.parse_value(val, &cerr)) {
|
||||
usage();
|
||||
}
|
||||
features.push_back(f);
|
||||
} else if (ceph_argparse_flag(args, i, "--optional", (char*)NULL)) {
|
||||
if (features.empty()) {
|
||||
usage();
|
||||
}
|
||||
features.back().set_optional();
|
||||
} else if (ceph_argparse_flag(args, i, "--persistent", (char*)NULL)) {
|
||||
if (features.empty()) {
|
||||
usage();
|
||||
}
|
||||
features.back().set_persistent();
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
@ -178,7 +363,11 @@ int main(int argc, const char **argv)
|
||||
monmap.remove(*p);
|
||||
}
|
||||
|
||||
if (!print && !modified)
|
||||
if (handle_features(features, monmap)) {
|
||||
modified = true;
|
||||
}
|
||||
|
||||
if (!print && !modified && !show_features)
|
||||
usage();
|
||||
|
||||
if (print)
|
||||
|
Loading…
Reference in New Issue
Block a user