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"
27 cout
<< " usage: [--print] [--create [--clobber][--fsid uuid]]\n"
28 << " [--generate] [--set-initial-members]\n"
29 << " [--add name 1.2.3.4:567] [--rm name]\n"
30 << " [--feature-list [plain|parseable]]\n"
31 << " [--feature-set <value> [--optional|--persistent]]\n"
32 << " [--feature-unset <value> [--optional|--persistent]] "
55 mon_feature_t feature
;
57 feature_op_t() : op(OP_LIST
), type(NONE
) { }
58 // default to 'persistent' feature if not specified
59 feature_op_t(op_t o
) : op(o
), type(PERSISTENT
) { }
60 feature_op_t(op_t o
, type_t t
) : op(o
), type(t
) { }
61 feature_op_t(op_t o
, type_t t
, mon_feature_t
&f
) :
62 op(o
), type(t
), feature(t
) { }
67 void set_persistent() {
70 bool parse_value(string
&s
, ostream
*errout
= NULL
) {
72 feature
= ceph::features::mon::get_feature_by_name(s
);
73 if (feature
!= ceph::features::mon::FEATURE_NONE
) {
77 // try parsing as numerical value
80 feature_val
= strict_strtoll(s
.c_str(), 10, &interr
);
81 if (!interr
.empty()) {
83 *errout
<< "unknown features name '" << s
84 << "' or unable to parse value: " << interr
<< std::endl
;
88 feature
= mon_feature_t(feature_val
);
93 void features_list(feature_op_t
&f
, MonMap
&m
)
95 if (f
.type
== feature_op_t::type_t::PLAIN
) {
97 cout
<< "MONMAP FEATURES:" << std::endl
;
98 cout
<< " persistent: ";
99 m
.persistent_features
.print_with_value(cout
);
101 cout
<< " optional: ";
102 m
.optional_features
.print_with_value(cout
);
104 cout
<< " required: ";
105 m
.get_required_features().print_with_value(cout
);
109 cout
<< "AVAILABLE FEATURES:" << std::endl
;
110 cout
<< " supported: ";
111 ceph::features::mon::get_supported().print_with_value(cout
);
113 cout
<< " persistent: ";
114 ceph::features::mon::get_persistent().print_with_value(cout
);
116 } else if (f
.type
== feature_op_t::type_t::PARSEABLE
) {
118 cout
<< "monmap:persistent:";
119 m
.persistent_features
.print_with_value(cout
);
121 cout
<< "monmap:optional:";
122 m
.optional_features
.print_with_value(cout
);
124 cout
<< "monmap:required:";
125 m
.get_required_features().print_with_value(cout
);
127 cout
<< "available:supported:";
128 ceph::features::mon::get_supported().print_with_value(cout
);
130 cout
<< "available:persistent:";
131 ceph::features::mon::get_persistent().print_with_value(cout
);
136 bool handle_features(list
<feature_op_t
>& lst
, MonMap
&m
)
141 bool modified
= false;
143 for (auto &f
: lst
) {
144 if (f
.op
== feature_op_t::op_t::OP_LIST
) {
146 } else if (f
.op
== feature_op_t::op_t::OP_SET
||
147 f
.op
== feature_op_t::op_t::OP_UNSET
) {
151 mon_feature_t
&target
=
152 ( f
.type
== feature_op_t::type_t::OPTIONAL
?
153 m
.optional_features
: m
.persistent_features
);
155 if (f
.op
== feature_op_t::op_t::OP_SET
) {
156 target
.set_feature(f
.feature
);
158 target
.unset_feature(f
.feature
);
161 cerr
<< "unknow feature operation type '" << f
.op
<< "'" << std::endl
;
167 int main(int argc
, const char **argv
)
169 vector
<const char*> args
;
170 argv_to_vec(argc
, argv
, args
);
172 const char *me
= argv
[0];
177 bool clobber
= false;
178 bool modified
= false;
179 bool show_features
= false;
180 bool generate
= false;
182 map
<string
,entity_addr_t
> add
;
184 list
<feature_op_t
> features
;
186 auto cct
= global_init(NULL
, args
, CEPH_ENTITY_TYPE_CLIENT
,
187 CODE_ENVIRONMENT_UTILITY
,
188 CINIT_FLAG_NO_DEFAULT_CONFIG_FILE
);
189 common_init_finish(g_ceph_context
);
191 for (std::vector
<const char*>::iterator i
= args
.begin(); i
!= args
.end(); ) {
192 if (ceph_argparse_double_dash(args
, i
)) {
194 } else if (ceph_argparse_flag(args
, i
, "-h", "--help", (char*)NULL
)) {
196 } else if (ceph_argparse_flag(args
, i
, "-p", "--print", (char*)NULL
)) {
198 } else if (ceph_argparse_flag(args
, i
, "--create", (char*)NULL
)) {
200 } else if (ceph_argparse_flag(args
, i
, "--clobber", (char*)NULL
)) {
202 } else if (ceph_argparse_flag(args
, i
, "--generate", (char*)NULL
)) {
204 } else if (ceph_argparse_flag(args
, i
, "--set-initial-members", (char*)NULL
)) {
206 } else if (ceph_argparse_flag(args
, i
, "--add", (char*)NULL
)) {
212 if (!addr
.parse(*i
)) {
213 cerr
<< me
<< ": invalid ip:port '" << *i
<< "'" << std::endl
;
216 if (addr
.get_port() == 0)
217 addr
.set_port(CEPH_MON_PORT
);
221 } else if (ceph_argparse_witharg(args
, i
, &val
, "--rm", (char*)NULL
)) {
224 } else if (ceph_argparse_flag(args
, i
, "--feature-list", (char*)NULL
)) {
226 if (format
== "plain" || format
== "parseable") {
232 feature_op_t
f(feature_op_t::op_t::OP_LIST
,
233 feature_op_t::type_t::PLAIN
);
235 if (format
== "parseable") {
236 f
.type
= feature_op_t::type_t::PARSEABLE
;
237 } else if (format
!= "plain") {
238 cerr
<< "invalid format type for list: '" << val
<< "'" << std::endl
;
242 features
.push_back(f
);
243 show_features
= true;
244 } else if (ceph_argparse_witharg(args
, i
, &val
,
245 "--feature-set", (char*)NULL
)) {
247 feature_op_t
f(feature_op_t::op_t::OP_SET
);
248 if (!f
.parse_value(val
, &cerr
)) {
251 features
.push_back(f
);
253 } else if (ceph_argparse_witharg(args
, i
, &val
,
254 "--feature-unset", (char*)NULL
)) {
256 feature_op_t
f(feature_op_t::op_t::OP_UNSET
);
257 if (!f
.parse_value(val
, &cerr
)) {
260 features
.push_back(f
);
261 } else if (ceph_argparse_flag(args
, i
, "--optional", (char*)NULL
)) {
262 if (features
.empty()) {
265 features
.back().set_optional();
266 } else if (ceph_argparse_flag(args
, i
, "--persistent", (char*)NULL
)) {
267 if (features
.empty()) {
270 features
.back().set_persistent();
276 cerr
<< me
<< ": must specify monmap filename" << std::endl
;
279 else if (args
.size() > 1) {
280 cerr
<< me
<< ": too many arguments" << std::endl
;
287 cout
<< me
<< ": monmap file " << fn
<< std::endl
;
290 if (!(create
&& clobber
)) {
292 r
= monmap
.read(fn
.c_str());
294 cerr
<< me
<< ": unable to read monmap file" << std::endl
;
299 if (!create
&& r
< 0) {
300 cerr
<< me
<< ": couldn't open " << fn
<< ": " << cpp_strerror(r
) << std::endl
;
303 else if (create
&& !clobber
&& r
== 0) {
304 cerr
<< me
<< ": " << fn
<< " exists, --clobber to overwrite" << std::endl
;
310 monmap
.created
= ceph_clock_now();
311 monmap
.last_changed
= monmap
.created
;
312 srand(getpid() + time(0));
313 if (g_conf
->get_val
<uuid_d
>("fsid").is_zero()) {
314 monmap
.generate_fsid();
315 cout
<< me
<< ": generated fsid " << monmap
.fsid
<< std::endl
;
321 int r
= monmap
.build_initial(g_ceph_context
, cerr
);
327 // apply initial members
328 list
<string
> initial_members
;
329 get_str_list(g_conf
->mon_initial_members
, initial_members
);
330 if (!initial_members
.empty()) {
331 cout
<< "initial_members " << initial_members
<< ", filtering seed monmap" << std::endl
;
332 set
<entity_addr_t
> removed
;
333 monmap
.set_initial_members(g_ceph_context
, initial_members
,
334 string(), entity_addr_t(),
336 cout
<< "removed " << removed
<< std::endl
;
341 if (!g_conf
->get_val
<uuid_d
>("fsid").is_zero()) {
342 monmap
.fsid
= g_conf
->get_val
<uuid_d
>("fsid");
343 cout
<< me
<< ": set fsid to " << monmap
.fsid
<< std::endl
;
347 for (map
<string
,entity_addr_t
>::iterator p
= add
.begin(); p
!= add
.end(); ++p
) {
348 if (monmap
.contains(p
->first
)) {
349 cerr
<< me
<< ": map already contains mon." << p
->first
<< std::endl
;
352 if (monmap
.contains(p
->second
)) {
353 cerr
<< me
<< ": map already contains " << p
->second
<< std::endl
;
356 monmap
.add(p
->first
, p
->second
);
358 for (list
<string
>::iterator p
= rm
.begin(); p
!= rm
.end(); ++p
) {
359 cout
<< me
<< ": removing " << *p
<< std::endl
;
360 if (!monmap
.contains(*p
)) {
361 cerr
<< me
<< ": map does not contain " << *p
<< std::endl
;
367 if (handle_features(features
, monmap
)) {
371 if (!print
&& !modified
&& !show_features
)
379 cout
<< me
<< ": writing epoch " << monmap
.epoch
381 << " (" << monmap
.size() << " monitors)"
383 int r
= monmap
.write(fn
.c_str());
385 cerr
<< "monmaptool: error writing to '" << fn
<< "': " << cpp_strerror(r
) << std::endl
;