1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
16 #include "common/ceph_argparse.h"
17 #include "common/errno.h"
19 #include "global/global_init.h"
20 #include "include/str_list.h"
21 #include "mon/MonMap.h"
26 cout
<< "usage: monmaptool [--print] [--create [--clobber] [--fsid uuid]]\n"
27 << " [--enable-all-features]\n"
28 << " [--generate] [--set-initial-members]\n"
29 << " [--add name 1.2.3.4:567] [--rm name]\n"
30 << " [--addv name [v2:1.2.4.5:567,v1:1.2.3.4:568]]\n"
31 << " [--feature-list [plain|parseable]]\n"
32 << " [--feature-set <value> [--optional|--persistent]]\n"
33 << " [--feature-unset <value> [--optional|--persistent]]\n"
34 << " [--set-min-mon-release <release-major-number>]\n"
41 cerr
<< "monmaptool -h for usage" << std::endl
;
62 mon_feature_t feature
;
64 feature_op_t() : op(OP_LIST
), type(NONE
) { }
65 // default to 'persistent' feature if not specified
66 feature_op_t(op_t o
) : op(o
), type(PERSISTENT
) { }
67 feature_op_t(op_t o
, type_t t
) : op(o
), type(t
) { }
68 feature_op_t(op_t o
, type_t t
, mon_feature_t
&f
) :
69 op(o
), type(t
), feature(t
) { }
74 void set_persistent() {
77 bool parse_value(string
&s
, ostream
*errout
= NULL
) {
79 feature
= ceph::features::mon::get_feature_by_name(s
);
80 if (feature
!= ceph::features::mon::FEATURE_NONE
) {
84 // try parsing as numerical value
87 feature_val
= strict_strtoll(s
.c_str(), 10, &interr
);
88 if (!interr
.empty()) {
90 *errout
<< "unknown features name '" << s
91 << "' or unable to parse value: " << interr
<< std::endl
;
95 feature
= mon_feature_t(feature_val
);
100 void features_list(feature_op_t
&f
, MonMap
&m
)
102 if (f
.type
== feature_op_t::type_t::PLAIN
) {
104 cout
<< "MONMAP FEATURES:" << std::endl
;
105 cout
<< " persistent: ";
106 m
.persistent_features
.print_with_value(cout
);
108 cout
<< " optional: ";
109 m
.optional_features
.print_with_value(cout
);
111 cout
<< " required: ";
112 m
.get_required_features().print_with_value(cout
);
116 cout
<< "AVAILABLE FEATURES:" << std::endl
;
117 cout
<< " supported: ";
118 ceph::features::mon::get_supported().print_with_value(cout
);
120 cout
<< " persistent: ";
121 ceph::features::mon::get_persistent().print_with_value(cout
);
123 } else if (f
.type
== feature_op_t::type_t::PARSEABLE
) {
125 cout
<< "monmap:persistent:";
126 m
.persistent_features
.print_with_value(cout
);
128 cout
<< "monmap:optional:";
129 m
.optional_features
.print_with_value(cout
);
131 cout
<< "monmap:required:";
132 m
.get_required_features().print_with_value(cout
);
134 cout
<< "available:supported:";
135 ceph::features::mon::get_supported().print_with_value(cout
);
137 cout
<< "available:persistent:";
138 ceph::features::mon::get_persistent().print_with_value(cout
);
143 bool handle_features(list
<feature_op_t
>& lst
, MonMap
&m
)
148 bool modified
= false;
150 for (auto &f
: lst
) {
151 if (f
.op
== feature_op_t::op_t::OP_LIST
) {
153 } else if (f
.op
== feature_op_t::op_t::OP_SET
||
154 f
.op
== feature_op_t::op_t::OP_UNSET
) {
158 mon_feature_t
&target
=
159 ( f
.type
== feature_op_t::type_t::OPTIONAL
?
160 m
.optional_features
: m
.persistent_features
);
162 if (f
.op
== feature_op_t::op_t::OP_SET
) {
163 target
.set_feature(f
.feature
);
165 target
.unset_feature(f
.feature
);
168 cerr
<< "unknown feature operation type '" << f
.op
<< "'" << std::endl
;
174 int main(int argc
, const char **argv
)
176 vector
<const char*> args
;
177 argv_to_vec(argc
, argv
, args
);
179 cerr
<< argv
[0] << ": -h or --help for usage" << std::endl
;
182 if (ceph_argparse_need_usage(args
)) {
187 const char *me
= argv
[0];
192 bool enable_all_features
= false;
193 bool clobber
= false;
194 bool modified
= false;
195 bool show_features
= false;
196 bool generate
= false;
198 ceph_release_t min_mon_release
{0};
199 map
<string
,entity_addr_t
> add
;
200 map
<string
,entity_addrvec_t
> addv
;
202 list
<feature_op_t
> features
;
204 auto cct
= global_init(NULL
, args
, CEPH_ENTITY_TYPE_CLIENT
,
205 CODE_ENVIRONMENT_UTILITY
,
206 CINIT_FLAG_NO_DEFAULT_CONFIG_FILE
);
207 common_init_finish(g_ceph_context
);
209 for (std::vector
<const char*>::iterator i
= args
.begin(); i
!= args
.end(); ) {
210 if (ceph_argparse_double_dash(args
, i
)) {
212 } else if (ceph_argparse_flag(args
, i
, "-p", "--print", (char*)NULL
)) {
214 } else if (ceph_argparse_flag(args
, i
, "--create", (char*)NULL
)) {
216 } else if (ceph_argparse_flag(args
, i
, "--enable-all-features", (char*)NULL
)) {
217 enable_all_features
= true;
218 } else if (ceph_argparse_flag(args
, i
, "--clobber", (char*)NULL
)) {
220 } else if (ceph_argparse_flag(args
, i
, "--generate", (char*)NULL
)) {
222 } else if (ceph_argparse_flag(args
, i
, "--set-initial-members", (char*)NULL
)) {
224 } else if (ceph_argparse_witharg(args
, i
, &val
, "--set-min-mon-release",
226 min_mon_release
= ceph_release_from_name(val
);
227 } else if (ceph_argparse_flag(args
, i
, "--add", (char*)NULL
)) {
233 if (!addr
.parse(*i
)) {
234 cerr
<< me
<< ": invalid ip:port '" << *i
<< "'" << std::endl
;
240 } else if (ceph_argparse_flag(args
, i
, "--addv", (char*)NULL
)) {
245 entity_addrvec_t addrs
;
246 if (!addrs
.parse(*i
)) {
247 cerr
<< me
<< ": invalid ip:port '" << *i
<< "'" << std::endl
;
253 } else if (ceph_argparse_witharg(args
, i
, &val
, "--rm", (char*)NULL
)) {
256 } else if (ceph_argparse_flag(args
, i
, "--feature-list", (char*)NULL
)) {
258 if (format
== "plain" || format
== "parseable") {
264 feature_op_t
f(feature_op_t::op_t::OP_LIST
,
265 feature_op_t::type_t::PLAIN
);
267 if (format
== "parseable") {
268 f
.type
= feature_op_t::type_t::PARSEABLE
;
269 } else if (format
!= "plain") {
270 cerr
<< "invalid format type for list: '" << val
<< "'" << std::endl
;
274 features
.push_back(f
);
275 show_features
= true;
276 } else if (ceph_argparse_witharg(args
, i
, &val
,
277 "--feature-set", (char*)NULL
)) {
279 feature_op_t
f(feature_op_t::op_t::OP_SET
);
280 if (!f
.parse_value(val
, &cerr
)) {
283 features
.push_back(f
);
285 } else if (ceph_argparse_witharg(args
, i
, &val
,
286 "--feature-unset", (char*)NULL
)) {
288 feature_op_t
f(feature_op_t::op_t::OP_UNSET
);
289 if (!f
.parse_value(val
, &cerr
)) {
292 features
.push_back(f
);
293 } else if (ceph_argparse_flag(args
, i
, "--optional", (char*)NULL
)) {
294 if (features
.empty()) {
297 features
.back().set_optional();
298 } else if (ceph_argparse_flag(args
, i
, "--persistent", (char*)NULL
)) {
299 if (features
.empty()) {
302 features
.back().set_persistent();
308 cerr
<< me
<< ": must specify monmap filename" << std::endl
;
311 else if (args
.size() > 1) {
312 cerr
<< me
<< ": too many arguments" << std::endl
;
319 cout
<< me
<< ": monmap file " << fn
<< std::endl
;
322 if (!(create
&& clobber
)) {
324 r
= monmap
.read(fn
.c_str());
326 cerr
<< me
<< ": unable to read monmap file" << std::endl
;
331 if (!create
&& r
< 0) {
332 cerr
<< me
<< ": couldn't open " << fn
<< ": " << cpp_strerror(r
) << std::endl
;
335 else if (create
&& !clobber
&& r
== 0) {
336 cerr
<< me
<< ": " << fn
<< " exists, --clobber to overwrite" << std::endl
;
342 monmap
.created
= ceph_clock_now();
343 monmap
.last_changed
= monmap
.created
;
344 srand(getpid() + time(0));
345 if (g_conf().get_val
<uuid_d
>("fsid").is_zero()) {
346 monmap
.generate_fsid();
347 cout
<< me
<< ": generated fsid " << monmap
.fsid
<< std::endl
;
351 if (enable_all_features
) {
352 // populate persistent features, too
353 monmap
.persistent_features
= ceph::features::mon::get_persistent();
358 int r
= monmap
.build_initial(g_ceph_context
, true, cerr
);
363 if (min_mon_release
!= ceph_release_t::unknown
) {
364 monmap
.min_mon_release
= min_mon_release
;
365 cout
<< "setting min_mon_release = " << min_mon_release
<< std::endl
;
370 // apply initial members
371 list
<string
> initial_members
;
372 get_str_list(g_conf()->mon_initial_members
, initial_members
);
373 if (!initial_members
.empty()) {
374 cout
<< "initial_members " << initial_members
<< ", filtering seed monmap" << std::endl
;
375 set
<entity_addrvec_t
> removed
;
376 monmap
.set_initial_members(g_ceph_context
, initial_members
,
377 string(), entity_addrvec_t(),
379 cout
<< "removed " << removed
<< std::endl
;
384 if (!g_conf().get_val
<uuid_d
>("fsid").is_zero()) {
385 monmap
.fsid
= g_conf().get_val
<uuid_d
>("fsid");
386 cout
<< me
<< ": set fsid to " << monmap
.fsid
<< std::endl
;
390 for (auto& p
: add
) {
391 entity_addr_t addr
= p
.second
;
392 entity_addrvec_t addrs
;
393 if (monmap
.contains(p
.first
)) {
394 cerr
<< me
<< ": map already contains mon." << p
.first
<< std::endl
;
397 if (addr
.get_port() == 0) {
398 if (monmap
.persistent_features
.contains_all(
399 ceph::features::mon::FEATURE_NAUTILUS
)) {
400 addr
.set_type(entity_addr_t::TYPE_MSGR2
);
401 addr
.set_port(CEPH_MON_PORT_IANA
);
402 addrs
.v
.push_back(addr
);
403 addr
.set_type(entity_addr_t::TYPE_LEGACY
);
404 addr
.set_port(CEPH_MON_PORT_LEGACY
);
405 addrs
.v
.push_back(addr
);
407 addr
.set_type(entity_addr_t::TYPE_LEGACY
);
408 addr
.set_port(CEPH_MON_PORT_LEGACY
);
409 addrs
.v
.push_back(addr
);
411 } else if (addr
.get_port() == CEPH_MON_PORT_LEGACY
) {
412 addr
.set_type(entity_addr_t::TYPE_LEGACY
);
413 addrs
.v
.push_back(addr
);
415 if (monmap
.persistent_features
.contains_all(
416 ceph::features::mon::FEATURE_NAUTILUS
)) {
417 addr
.set_type(entity_addr_t::TYPE_MSGR2
);
419 addrs
.v
.push_back(addr
);
421 if (monmap
.contains(addrs
)) {
422 cerr
<< me
<< ": map already contains " << addrs
<< std::endl
;
425 monmap
.add(p
.first
, addrs
);
427 for (auto& p
: addv
) {
428 if (monmap
.contains(p
.first
)) {
429 cerr
<< me
<< ": map already contains mon." << p
.first
<< std::endl
;
432 if (monmap
.contains(p
.second
)) {
433 cerr
<< me
<< ": map already contains " << p
.second
<< std::endl
;
436 monmap
.add(p
.first
, p
.second
);
439 cout
<< me
<< ": removing " << p
<< std::endl
;
440 if (!monmap
.contains(p
)) {
441 cerr
<< me
<< ": map does not contain " << p
<< std::endl
;
447 if (handle_features(features
, monmap
)) {
451 if (!print
&& !modified
&& !show_features
) {
452 cerr
<< "no action specified" << std::endl
;
461 cout
<< me
<< ": writing epoch " << monmap
.epoch
463 << " (" << monmap
.size() << " monitors)"
465 int r
= monmap
.write(fn
.c_str());
467 cerr
<< "monmaptool: error writing to '" << fn
<< "': " << cpp_strerror(r
) << std::endl
;