1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
12 #include <seastar/core/fstream.hh>
13 #include <seastar/core/reactor.hh>
14 #include <seastar/net/dns.hh>
15 #include "crimson/common/config_proxy.h"
18 #include "common/Formatter.h"
20 #include "include/ceph_features.h"
21 #include "include/addr_parsing.h"
22 #include "common/ceph_argparse.h"
23 #include "common/dns_resolve.h"
24 #include "common/errno.h"
25 #include "common/dout.h"
26 #include "common/Clock.h"
35 using ceph::DNSResolver
;
36 using ceph::Formatter
;
38 void mon_info_t::encode(ceph::buffer::list
& bl
, uint64_t features
) const
41 if (!HAVE_FEATURE(features
, SERVER_NAUTILUS
)) {
44 ENCODE_START(v
, 1, bl
);
47 auto a
= public_addrs
.legacy_addr();
48 if (a
!= entity_addr_t()) {
49 encode(a
, bl
, features
);
51 // note: we don't have a legacy addr here, so lie so that it looks
52 // like one, just so that old clients get a valid-looking map.
53 // they won't be able to talk to the v2 mons, but that's better
55 encode(public_addrs
.as_legacy_addr(), bl
, features
);
58 encode(public_addrs
, bl
, features
);
65 void mon_info_t::decode(ceph::buffer::list::const_iterator
& p
)
69 decode(public_addrs
, p
);
79 void mon_info_t::print(ostream
& out
) const
82 << " addrs " << public_addrs
83 << " priority " << priority
84 << " weight " << weight
;
89 bool operator()(const mon_info_t
&a
, const mon_info_t
&b
) const {
90 if (a
.public_addrs
.legacy_or_front_addr() == b
.public_addrs
.legacy_or_front_addr())
91 return a
.name
< b
.name
;
92 return a
.public_addrs
.legacy_or_front_addr() < b
.public_addrs
.legacy_or_front_addr();
97 void MonMap::calc_legacy_ranks()
99 ranks
.resize(mon_info
.size());
101 // Used to order entries according to public_addr, because that's
102 // how the ranks are expected to be ordered by. We may expand this
103 // later on, according to some other criteria, by specifying a
104 // different comparator.
106 // Please note that we use a 'set' here instead of resorting to
107 // std::sort() because we need more info than that's available in
108 // the vector. The vector will thus be ordered by, e.g., public_addr
109 // while only containing the names of each individual monitor.
110 // The only way of achieving this with std::sort() would be to first
111 // insert every mon_info_t entry into a vector 'foo', std::sort() 'foo'
112 // with custom comparison functions, and then copy each invidual entry
113 // to a new vector. Unless there's a simpler way, we don't think the
114 // added complexity makes up for the additional memory usage of a 'set'.
115 set
<mon_info_t
, rank_cmp
> tmp
;
117 for (auto p
= mon_info
.begin(); p
!= mon_info
.end(); ++p
) {
118 mon_info_t
&m
= p
->second
;
122 // map the set to the actual ranks etc
124 for (auto p
= tmp
.begin(); p
!= tmp
.end(); ++p
, ++i
) {
129 void MonMap::encode(ceph::buffer::list
& blist
, uint64_t con_features
) const
131 if ((con_features
& CEPH_FEATURE_MONNAMES
) == 0) {
135 ceph::encode_raw(fsid
, blist
);
136 encode(epoch
, blist
);
137 vector
<entity_inst_t
> mon_inst(ranks
.size());
138 for (unsigned n
= 0; n
< ranks
.size(); n
++) {
139 mon_inst
[n
].name
= entity_name_t::MON(n
);
140 mon_inst
[n
].addr
= get_addrs(n
).legacy_addr();
142 encode(mon_inst
, blist
, con_features
);
143 encode(last_changed
, blist
);
144 encode(created
, blist
);
148 map
<string
,entity_addr_t
> legacy_mon_addr
;
149 if (!HAVE_FEATURE(con_features
, MONENC
) ||
150 !HAVE_FEATURE(con_features
, SERVER_NAUTILUS
)) {
151 for (auto& [name
, info
] : mon_info
) {
152 legacy_mon_addr
[name
] = info
.public_addrs
.legacy_addr();
156 if (!HAVE_FEATURE(con_features
, MONENC
)) {
157 /* we keep the mon_addr map when encoding to ensure compatibility
158 * with clients and other monitors that do not yet support the 'mons'
159 * map. This map keeps its original behavior, containing a mapping of
160 * monitor id (i.e., 'foo' in 'mon.foo') to the monitor's public
161 * address -- which is obtained from the public address of each entry
167 ceph::encode_raw(fsid
, blist
);
168 encode(epoch
, blist
);
169 encode(legacy_mon_addr
, blist
, con_features
);
170 encode(last_changed
, blist
);
171 encode(created
, blist
);
175 if (!HAVE_FEATURE(con_features
, SERVER_NAUTILUS
)) {
176 ENCODE_START(5, 3, blist
);
177 ceph::encode_raw(fsid
, blist
);
178 encode(epoch
, blist
);
179 encode(legacy_mon_addr
, blist
, con_features
);
180 encode(last_changed
, blist
);
181 encode(created
, blist
);
182 encode(persistent_features
, blist
);
183 encode(optional_features
, blist
);
184 encode(mon_info
, blist
, con_features
);
185 ENCODE_FINISH(blist
);
189 ENCODE_START(7, 6, blist
);
190 ceph::encode_raw(fsid
, blist
);
191 encode(epoch
, blist
);
192 encode(last_changed
, blist
);
193 encode(created
, blist
);
194 encode(persistent_features
, blist
);
195 encode(optional_features
, blist
);
196 encode(mon_info
, blist
, con_features
);
197 encode(ranks
, blist
);
198 encode(min_mon_release
, blist
);
199 ENCODE_FINISH(blist
);
202 void MonMap::decode(ceph::buffer::list::const_iterator
& p
)
204 map
<string
,entity_addr_t
> mon_addr
;
205 DECODE_START_LEGACY_COMPAT_LEN_16(7, 3, 3, p
);
206 ceph::decode_raw(fsid
, p
);
209 vector
<entity_inst_t
> mon_inst
;
211 for (unsigned i
= 0; i
< mon_inst
.size(); i
++) {
216 mon_addr
[name
] = mon_inst
[i
].addr
;
218 } else if (struct_v
< 6) {
221 decode(last_changed
, p
);
224 decode(persistent_features
, p
);
225 decode(optional_features
, p
);
228 // generate mon_info from legacy mon_addr
229 for (auto& [name
, addr
] : mon_addr
) {
230 mon_info_t
&m
= mon_info
[name
];
232 m
.public_addrs
= entity_addrvec_t(addr
);
243 decode(min_mon_release
, p
);
245 min_mon_release
= infer_ceph_release_from_mon_features(persistent_features
);
251 void MonMap::generate_test_instances(list
<MonMap
*>& o
)
253 o
.push_back(new MonMap
);
254 o
.push_back(new MonMap
);
256 o
.back()->last_changed
= utime_t(123, 456);
257 o
.back()->created
= utime_t(789, 101112);
258 o
.back()->add("one", entity_addrvec_t());
260 MonMap
*m
= new MonMap
;
263 m
->last_changed
= utime_t(123, 456);
265 entity_addrvec_t empty_addr_one
= entity_addrvec_t(entity_addr_t());
266 empty_addr_one
.v
[0].set_nonce(1);
267 m
->add("empty_addr_one", empty_addr_one
);
268 entity_addrvec_t empty_addr_two
= entity_addrvec_t(entity_addr_t());
269 empty_addr_two
.v
[0].set_nonce(2);
270 m
->add("empty_addr_two", empty_addr_two
);
272 const char *local_pub_addr_s
= "127.0.1.2";
274 const char *end_p
= local_pub_addr_s
+ strlen(local_pub_addr_s
);
275 entity_addrvec_t local_pub_addr
;
276 local_pub_addr
.parse(local_pub_addr_s
, &end_p
);
278 m
->add(mon_info_t("filled_pub_addr", entity_addrvec_t(local_pub_addr
), 1, 1));
280 m
->add("empty_addr_zero", entity_addrvec_t());
285 // read from/write to a file
286 int MonMap::write(const char *fn
)
289 ceph::buffer::list bl
;
290 encode(bl
, CEPH_FEATURES_ALL
);
292 return bl
.write_file(fn
);
295 int MonMap::read(const char *fn
)
298 ceph::buffer::list bl
;
300 int r
= bl
.read_file(fn
, &error
);
307 void MonMap::print_summary(ostream
& out
) const
309 out
<< "e" << epoch
<< ": "
310 << mon_info
.size() << " mons at {";
311 // the map that we used to print, as it was, no longer
312 // maps strings to the monitor's public address, but to
313 // mon_info_t instead. As such, print the map in a way
314 // that keeps the expected format.
315 bool has_printed
= false;
316 for (auto p
= mon_info
.begin(); p
!= mon_info
.end(); ++p
) {
319 out
<< p
->first
<< "=" << p
->second
.public_addrs
;
325 void MonMap::print(ostream
& out
) const
327 out
<< "epoch " << epoch
<< "\n";
328 out
<< "fsid " << fsid
<< "\n";
329 out
<< "last_changed " << last_changed
<< "\n";
330 out
<< "created " << created
<< "\n";
331 out
<< "min_mon_release " << ceph::to_integer
<unsigned>(min_mon_release
)
332 << " (" << min_mon_release
<< ")\n";
334 for (auto p
= ranks
.begin(); p
!= ranks
.end(); ++p
) {
335 out
<< i
++ << ": " << get_addrs(*p
) << " mon." << *p
<< "\n";
339 void MonMap::dump(Formatter
*f
) const
341 f
->dump_unsigned("epoch", epoch
);
342 f
->dump_stream("fsid") << fsid
;
343 last_changed
.gmtime(f
->dump_stream("modified"));
344 created
.gmtime(f
->dump_stream("created"));
345 f
->dump_unsigned("min_mon_release", ceph::to_integer
<unsigned>(min_mon_release
));
346 f
->dump_string("min_mon_release_name", ceph::to_string(min_mon_release
));
347 f
->open_object_section("features");
348 persistent_features
.dump(f
, "persistent");
349 optional_features
.dump(f
, "optional");
351 f
->open_array_section("mons");
353 for (auto p
= ranks
.begin(); p
!= ranks
.end(); ++p
, ++i
) {
354 f
->open_object_section("mon");
355 f
->dump_int("rank", i
);
356 f
->dump_string("name", *p
);
357 f
->dump_object("public_addrs", get_addrs(*p
));
358 // compat: make these look like pre-nautilus entity_addr_t
359 f
->dump_stream("addr") << get_addrs(*p
).get_legacy_str();
360 f
->dump_stream("public_addr") << get_addrs(*p
).get_legacy_str();
361 f
->dump_unsigned("priority", get_priority(*p
));
362 f
->dump_unsigned("weight", get_weight(*p
));
368 void MonMap::dump_summary(Formatter
*f
) const
370 f
->dump_unsigned("epoch", epoch
);
371 f
->dump_string("min_mon_release_name", ceph::to_string(min_mon_release
));
372 f
->dump_unsigned("num_mons", ranks
.size());
376 // an ambiguous mon addr may be legacy or may be msgr2--we aren' sure.
377 // when that happens we need to try them both (unless we can
378 // reasonably infer from the port number which it is).
379 void MonMap::_add_ambiguous_addr(const string
& name
,
385 if (addr
.get_type() != entity_addr_t::TYPE_ANY
) {
386 // a v1: or v2: prefix was specified
387 if (addr
.get_port() == 0) {
389 if (addr
.get_type() == entity_addr_t::TYPE_LEGACY
) {
390 addr
.set_port(CEPH_MON_PORT_LEGACY
);
391 } else if (addr
.get_type() == entity_addr_t::TYPE_MSGR2
) {
392 addr
.set_port(CEPH_MON_PORT_IANA
);
397 if (!contains(addr
)) {
398 add(name
, entity_addrvec_t(addr
), priority
, weight
);
401 if (!contains(addr
)) {
402 add(name
, entity_addrvec_t(addr
), priority
, weight
);
406 // no v1: or v2: prefix specified
407 if (addr
.get_port() == CEPH_MON_PORT_LEGACY
) {
408 // legacy port implies legacy addr
409 addr
.set_type(entity_addr_t::TYPE_LEGACY
);
410 if (!contains(addr
)) {
412 add(name
+ "-legacy", entity_addrvec_t(addr
), priority
, weight
);
414 add(name
, entity_addrvec_t(addr
), priority
, weight
);
417 } else if (addr
.get_port() == CEPH_MON_PORT_IANA
) {
418 // iana port implies msgr2 addr
419 addr
.set_type(entity_addr_t::TYPE_MSGR2
);
420 if (!contains(addr
)) {
421 add(name
, entity_addrvec_t(addr
), priority
, weight
);
423 } else if (addr
.get_port() == 0) {
424 // no port; include both msgr2 and legacy ports
426 addr
.set_type(entity_addr_t::TYPE_MSGR2
);
427 addr
.set_port(CEPH_MON_PORT_IANA
);
428 if (!contains(addr
)) {
429 add(name
, entity_addrvec_t(addr
), priority
, weight
);
431 addr
.set_type(entity_addr_t::TYPE_LEGACY
);
432 addr
.set_port(CEPH_MON_PORT_LEGACY
);
433 if (!contains(addr
)) {
434 add(name
+ "-legacy", entity_addrvec_t(addr
), priority
, weight
);
438 addr
.set_type(entity_addr_t::TYPE_MSGR2
);
439 addr
.set_port(CEPH_MON_PORT_IANA
);
440 av
.v
.push_back(addr
);
441 addr
.set_type(entity_addr_t::TYPE_LEGACY
);
442 addr
.set_port(CEPH_MON_PORT_LEGACY
);
443 av
.v
.push_back(addr
);
445 add(name
, av
, priority
, weight
);
449 addr
.set_type(entity_addr_t::TYPE_MSGR2
);
450 if (!contains(addr
)) {
451 add(name
, entity_addrvec_t(addr
), priority
, weight
);
454 // try legacy on same port too
455 addr
.set_type(entity_addr_t::TYPE_LEGACY
);
456 if (!contains(addr
)) {
457 add(name
+ "-legacy", entity_addrvec_t(addr
), priority
, weight
);
464 int MonMap::init_with_ips(const std::string
& ips
,
466 const std::string
&prefix
)
468 vector
<entity_addrvec_t
> addrs
;
469 if (!parse_ip_port_vec(
471 entity_addr_t::TYPE_ANY
)) {
476 for (unsigned i
=0; i
<addrs
.size(); i
++) {
483 if (addrs
[i
].v
.size() == 1) {
484 _add_ambiguous_addr(name
, addrs
[i
].front(), 0, 0, for_mkfs
);
486 // they specified an addrvec, so let's assume they also specified
487 // the addr *type* and *port*. (we could possibly improve this?)
488 add(name
, addrs
[i
], 0);
494 int MonMap::init_with_hosts(const std::string
& hostlist
,
496 const std::string
& prefix
)
498 // maybe they passed us a DNS-resolvable name
499 char *hosts
= resolve_addrs(hostlist
.c_str());
503 vector
<entity_addrvec_t
> addrs
;
504 bool success
= parse_ip_port_vec(
506 entity_addr_t::TYPE_ANY
);
512 for (unsigned i
=0; i
<addrs
.size(); i
++) {
516 string name
= prefix
;
518 if (addrs
[i
].v
.size() == 1) {
519 _add_ambiguous_addr(name
, addrs
[i
].front(), 0, 0, for_mkfs
);
521 // they specified an addrvec, so let's assume they also specified
522 // the addr *type* and *port*. (we could possibly improve this?)
523 add(name
, addrs
[i
], 0);
530 void MonMap::set_initial_members(CephContext
*cct
,
531 list
<std::string
>& initial_members
,
533 const entity_addrvec_t
& my_addrs
,
534 set
<entity_addrvec_t
> *removed
)
536 // remove non-initial members
539 string n
= get_name(i
);
540 if (std::find(initial_members
.begin(), initial_members
.end(), n
)
541 != initial_members
.end()) {
542 lgeneric_dout(cct
, 1) << " keeping " << n
<< " " << get_addrs(i
) << dendl
;
547 lgeneric_dout(cct
, 1) << " removing " << get_name(i
) << " " << get_addrs(i
)
550 removed
->insert(get_addrs(i
));
553 ceph_assert(!contains(n
));
556 // add missing initial members
557 for (auto& p
: initial_members
) {
560 lgeneric_dout(cct
, 1) << " adding self " << p
<< " " << my_addrs
565 a
.set_type(entity_addr_t::TYPE_LEGACY
);
566 a
.set_family(AF_INET
);
567 for (int n
=1; ; n
++) {
572 lgeneric_dout(cct
, 1) << " adding " << p
<< " " << a
<< dendl
;
573 add(p
, entity_addrvec_t(a
));
575 ceph_assert(contains(p
));
581 int MonMap::init_with_config_file(const ConfigProxy
& conf
,
582 std::ostream
& errout
)
584 std::vector
<std::string
> sections
;
585 int ret
= conf
.get_all_sections(sections
);
587 errout
<< "Unable to find any monitors in the configuration "
588 << "file, because there was an error listing the sections. error "
592 std::vector
<std::string
> mon_names
;
593 for (const auto& section
: sections
) {
594 if (section
.substr(0, 4) == "mon." && section
.size() > 4) {
595 mon_names
.push_back(section
.substr(4));
599 // Find an address for each monitor in the config file.
600 for (const auto& mon_name
: mon_names
) {
601 std::vector
<std::string
> sections
;
602 std::string
m_name("mon");
605 sections
.push_back(m_name
);
606 sections
.push_back("mon");
607 sections
.push_back("global");
609 int res
= conf
.get_val_from_conf_file(sections
, "mon addr", val
, true);
611 errout
<< "failed to get an address for mon." << mon_name
612 << ": error " << res
<< std::endl
;
615 // the 'mon addr' field is a legacy field, so assume anything
616 // there on a weird port is a v1 address, and do not handle
619 if (!addr
.parse(val
.c_str(), nullptr, entity_addr_t::TYPE_LEGACY
)) {
620 errout
<< "unable to parse address for mon." << mon_name
621 << ": addr='" << val
<< "'" << std::endl
;
624 if (addr
.get_port() == 0) {
625 addr
.set_port(CEPH_MON_PORT_LEGACY
);
627 uint16_t priority
= 0;
628 if (!conf
.get_val_from_conf_file(sections
, "mon priority", val
, false)) {
630 priority
= std::stoul(val
);
631 } catch (std::logic_error
&) {
632 errout
<< "unable to parse priority for mon." << mon_name
633 << ": priority='" << val
<< "'" << std::endl
;
638 if (!conf
.get_val_from_conf_file(sections
, "mon weight", val
, false)) {
640 weight
= std::stoul(val
);
641 } catch (std::logic_error
&) {
642 errout
<< "unable to parse weight for mon." << mon_name
643 << ": weight='" << val
<< "'"
649 // make sure this mon isn't already in the map
651 remove(get_name(addr
));
652 if (contains(mon_name
))
654 _add_ambiguous_addr(mon_name
, addr
, priority
, weight
, false);
661 using namespace seastar
;
663 future
<> MonMap::read_monmap(const std::string
& monmap
)
665 return open_file_dma(monmap
, open_flags::ro
).then([this] (file f
) {
666 return f
.size().then([this, f
= std::move(f
)](size_t s
) {
667 return do_with(make_file_input_stream(f
), [this, s
](input_stream
<char>& in
) {
668 return in
.read_exactly(s
).then([this](temporary_buffer
<char> buf
) {
669 ceph::buffer::list bl
;
670 bl
.push_back(ceph::buffer::ptr_node::create(
671 ceph::buffer::create(std::move(buf
))));
679 future
<> MonMap::init_with_dns_srv(bool for_mkfs
, const std::string
& name
)
682 string service
= name
;
683 // check if domain is also provided and extract it from srv_name
684 size_t idx
= name
.find("_");
685 if (idx
!= name
.npos
) {
686 domain
= name
.substr(idx
+ 1);
687 service
= name
.substr(0, idx
);
689 return seastar::net::dns::get_srv_records(
690 seastar::net::dns_resolver::srv_proto::tcp
,
691 service
, domain
).then([this](seastar::net::dns_resolver::srv_records records
) {
692 return parallel_for_each(records
, [this](auto record
) {
693 return seastar::net::dns::resolve_name(record
.target
).then(
694 [record
,this](seastar::net::inet_address a
) {
695 // the resolved address does not contain ceph specific info like nonce
696 // nonce or msgr proto (legacy, msgr2), so set entity_addr_t manually
698 addr
.set_type(entity_addr_t::TYPE_ANY
);
699 addr
.set_family(int(a
.in_family()));
700 addr
.set_port(record
.port
);
701 switch (a
.in_family()) {
702 case seastar::net::inet_address::family::INET
:
703 addr
.in4_addr().sin_addr
= a
;
705 case seastar::net::inet_address::family::INET6
:
706 addr
.in6_addr().sin6_addr
= a
;
709 _add_ambiguous_addr(record
.target
,
716 }).handle_exception_type([](const std::system_error
& e
) {
717 // ignore DNS failures
718 return seastar::make_ready_future
<>();
722 seastar::future
<> MonMap::build_monmap(const crimson::common::ConfigProxy
& conf
,
726 if (const auto mon_host
= conf
.get_val
<std::string
>("mon_host");
728 if (auto ret
= init_with_ips(mon_host
, for_mkfs
, "noname-"); ret
== 0) {
729 return make_ready_future
<>();
731 // TODO: resolve_addrs() is a blocking call
732 if (auto ret
= init_with_hosts(mon_host
, for_mkfs
, "noname-"); ret
== 0) {
733 return make_ready_future
<>();
735 throw std::runtime_error(cpp_strerror(ret
));
739 // What monitors are in the config file?
740 ostringstream errout
;
741 if (auto ret
= init_with_config_file(conf
, errout
); ret
< 0) {
742 throw std::runtime_error(errout
.str());
745 return make_ready_future
<>();
747 // no info found from conf options lets try use DNS SRV records
748 const string srv_name
= conf
.get_val
<std::string
>("mon_dns_srv_name");
749 return init_with_dns_srv(for_mkfs
, srv_name
).then([this] {
751 throw std::runtime_error("no monitors specified to connect to.");
756 future
<> MonMap::build_initial(const crimson::common::ConfigProxy
& conf
, bool for_mkfs
)
759 if (const auto monmap
= conf
.get_val
<std::string
>("monmap");
761 return read_monmap(monmap
);
764 if (const auto new_fsid
= conf
.get_val
<uuid_d
>("fsid");
765 !new_fsid
.is_zero()) {
768 return build_monmap(conf
, for_mkfs
).then([this] {
769 created
= ceph_clock_now();
770 last_changed
= created
;
776 #else // WITH_SEASTAR
778 int MonMap::init_with_monmap(const std::string
& monmap
, std::ostream
& errout
)
782 r
= read(monmap
.c_str());
783 } catch (ceph::buffer::error
&) {
788 errout
<< "unable to read/decode monmap from " << monmap
789 << ": " << cpp_strerror(-r
) << std::endl
;
793 int MonMap::init_with_dns_srv(CephContext
* cct
,
794 std::string srv_name
,
796 std::ostream
& errout
)
799 // check if domain is also provided and extract it from srv_name
800 size_t idx
= srv_name
.find("_");
801 if (idx
!= string::npos
) {
802 domain
= srv_name
.substr(idx
+ 1);
803 srv_name
= srv_name
.substr(0, idx
);
806 map
<string
, DNSResolver::Record
> records
;
807 if (DNSResolver::get_instance()->resolve_srv_hosts(cct
, srv_name
,
808 DNSResolver::SRV_Protocol::TCP
, domain
, &records
) != 0) {
810 errout
<< "unable to get monitor info from DNS SRV with service name: "
811 << "ceph-mon" << std::endl
;
814 for (auto& record
: records
) {
815 record
.second
.addr
.set_type(entity_addr_t::TYPE_ANY
);
816 _add_ambiguous_addr(record
.first
,
818 record
.second
.priority
,
819 record
.second
.weight
,
826 int MonMap::build_initial(CephContext
*cct
, bool for_mkfs
, ostream
& errout
)
828 const auto& conf
= cct
->_conf
;
830 if (const auto monmap
= conf
.get_val
<std::string
>("monmap");
832 return init_with_monmap(monmap
, errout
);
836 if (const auto new_fsid
= conf
.get_val
<uuid_d
>("fsid");
837 !new_fsid
.is_zero()) {
841 if (const auto mon_host
= conf
.get_val
<std::string
>("mon_host");
843 auto ret
= init_with_ips(mon_host
, for_mkfs
, "noname-");
844 if (ret
== -EINVAL
) {
845 ret
= init_with_hosts(mon_host
, for_mkfs
, "noname-");
848 errout
<< "unable to parse addrs in '" << mon_host
<< "'"
854 // What monitors are in the config file?
855 if (auto ret
= init_with_config_file(conf
, errout
); ret
< 0) {
860 // no info found from conf options lets try use DNS SRV records
861 string srv_name
= conf
.get_val
<std::string
>("mon_dns_srv_name");
862 if (auto ret
= init_with_dns_srv(cct
, srv_name
, for_mkfs
, errout
); ret
< 0) {
867 errout
<< "no monitors specified to connect to." << std::endl
;
870 created
= ceph_clock_now();
871 last_changed
= created
;
875 #endif // WITH_SEASTAR