]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/mon/MonMap.cc
import ceph quincy 17.2.6
[ceph.git] / ceph / src / mon / MonMap.cc
index 90330a1dab387f7c93a459332a191ddc27f223f8..33b9aa8fa2880e5f4fd79a3e1c5e6368d723cf33 100644 (file)
@@ -4,6 +4,7 @@
 #include "MonMap.h"
 
 #include <algorithm>
+#include <sstream>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include "common/errno.h"
 #include "common/dout.h"
 #include "common/Clock.h"
+#include "mon/health_check.h"
 
+using std::list;
+using std::map;
+using std::ostream;
+using std::ostringstream;
+using std::set;
+using std::string;
+using std::vector;
+
+using ceph::DNSResolver;
 using ceph::Formatter;
 
-void mon_info_t::encode(bufferlist& bl, uint64_t features) const
+#ifdef WITH_SEASTAR
+namespace {
+  seastar::logger& logger()
+  {
+    return crimson::get_logger(ceph_subsys_monc);
+  }
+}
+#endif
+
+void mon_info_t::encode(ceph::buffer::list& bl, uint64_t features) const
 {
-  uint8_t v = 3;
+  uint8_t v = 5;
+  uint8_t min_v = 1;
+  if (!crush_loc.empty()) {
+    // we added crush_loc in version 5, but need to let old clients decode it
+    // so just leave the min_v at version 1. Monitors are protected
+    // from misunderstandings about location because setting it is blocked
+    // on FEATURE_PINGING
+    min_v = 1;
+  }
   if (!HAVE_FEATURE(features, SERVER_NAUTILUS)) {
     v = 2;
   }
-  ENCODE_START(v, 1, bl);
+  ENCODE_START(v, min_v, bl);
   encode(name, bl);
   if (v < 3) {
-    encode(public_addrs.legacy_addr(), bl, features);
+    ceph_assert(min_v == 1);
+    auto a = public_addrs.legacy_addr();
+    if (a != entity_addr_t()) {
+      encode(a, bl, features);
+    } else {
+      // note: we don't have a legacy addr here, so lie so that it looks
+      // like one, just so that old clients get a valid-looking map.
+      // they won't be able to talk to the v2 mons, but that's better
+      // than nothing.
+      encode(public_addrs.as_legacy_addr(), bl, features);
+    }
   } else {
     encode(public_addrs, bl, features);
   }
   encode(priority, bl);
+  encode(weight, bl);
+  encode(crush_loc, bl);
   ENCODE_FINISH(bl);
 }
 
-void mon_info_t::decode(bufferlist::const_iterator& p)
+void mon_info_t::decode(ceph::buffer::list::const_iterator& p)
 {
-  DECODE_START(3, p);
+  DECODE_START(5, p);
   decode(name, p);
   decode(public_addrs, p);
   if (struct_v >= 2) {
     decode(priority, p);
   }
+  if (struct_v >= 4) {
+    decode(weight, p);
+  }
+  if (struct_v >= 5) {
+    decode(crush_loc, p);
+  }
   DECODE_FINISH(p);
 }
 
@@ -59,7 +105,9 @@ void mon_info_t::print(ostream& out) const
 {
   out << "mon." << name
       << " addrs " << public_addrs
-      << " priority " << priority;
+      << " priority " << priority
+      << " weight " << weight
+      << " crush location " << crush_loc;
 }
 
 namespace {
@@ -92,29 +140,25 @@ void MonMap::calc_legacy_ranks()
   // added complexity makes up for the additional memory usage of a 'set'.
   set<mon_info_t, rank_cmp> tmp;
 
-  for (map<string,mon_info_t>::iterator p = mon_info.begin();
-      p != mon_info.end();
-      ++p) {
+  for (auto p = mon_info.begin(); p != mon_info.end(); ++p) {
     mon_info_t &m = p->second;
     tmp.insert(m);
   }
 
   // map the set to the actual ranks etc
   unsigned i = 0;
-  for (set<mon_info_t>::iterator p = tmp.begin();
-      p != tmp.end();
-      ++p, ++i) {
+  for (auto p = tmp.begin(); p != tmp.end(); ++p, ++i) {
     ranks[i] = p->name;
   }
 }
 
-void MonMap::encode(bufferlist& blist, uint64_t con_features) const
+void MonMap::encode(ceph::buffer::list& blist, uint64_t con_features) const
 {
   if ((con_features & CEPH_FEATURE_MONNAMES) == 0) {
     using ceph::encode;
     __u16 v = 1;
     encode(v, blist);
-    encode_raw(fsid, blist);
+    ceph::encode_raw(fsid, blist);
     encode(epoch, blist);
     vector<entity_inst_t> mon_inst(ranks.size());
     for (unsigned n = 0; n < ranks.size(); n++) {
@@ -146,7 +190,7 @@ void MonMap::encode(bufferlist& blist, uint64_t con_features) const
     using ceph::encode;
     __u16 v = 2;
     encode(v, blist);
-    encode_raw(fsid, blist);
+    ceph::encode_raw(fsid, blist);
     encode(epoch, blist);
     encode(legacy_mon_addr, blist, con_features);
     encode(last_changed, blist);
@@ -156,7 +200,7 @@ void MonMap::encode(bufferlist& blist, uint64_t con_features) const
 
   if (!HAVE_FEATURE(con_features, SERVER_NAUTILUS)) {
     ENCODE_START(5, 3, blist);
-    encode_raw(fsid, blist);
+    ceph::encode_raw(fsid, blist);
     encode(epoch, blist);
     encode(legacy_mon_addr, blist, con_features);
     encode(last_changed, blist);
@@ -168,8 +212,8 @@ void MonMap::encode(bufferlist& blist, uint64_t con_features) const
     return;
   }
 
-  ENCODE_START(7, 6, blist);
-  encode_raw(fsid, blist);
+  ENCODE_START(9, 6, blist);
+  ceph::encode_raw(fsid, blist);
   encode(epoch, blist);
   encode(last_changed, blist);
   encode(created, blist);
@@ -178,14 +222,21 @@ void MonMap::encode(bufferlist& blist, uint64_t con_features) const
   encode(mon_info, blist, con_features);
   encode(ranks, blist);
   encode(min_mon_release, blist);
+  encode(removed_ranks, blist);
+  uint8_t t = strategy;
+  encode(t, blist);
+  encode(disallowed_leaders, blist);
+  encode(stretch_mode_enabled, blist);
+  encode(tiebreaker_mon, blist);
+  encode(stretch_marked_down_mons, blist);
   ENCODE_FINISH(blist);
 }
 
-void MonMap::decode(bufferlist::const_iterator& p)
+void MonMap::decode(ceph::buffer::list::const_iterator& p)
 {
   map<string,entity_addr_t> mon_addr;
-  DECODE_START_LEGACY_COMPAT_LEN_16(7, 3, 3, p);
-  decode_raw(fsid, p);
+  DECODE_START_LEGACY_COMPAT_LEN_16(9, 3, 3, p);
+  ceph::decode_raw(fsid, p);
   decode(epoch, p);
   if (struct_v == 1) {
     vector<entity_inst_t> mon_inst;
@@ -226,6 +277,22 @@ void MonMap::decode(bufferlist::const_iterator& p)
   } else {
     min_mon_release = infer_ceph_release_from_mon_features(persistent_features);
   }
+  if (struct_v >= 8) {
+    decode(removed_ranks, p);
+    uint8_t t;
+    decode(t, p);
+    strategy = static_cast<election_strategy>(t);
+    decode(disallowed_leaders, p);
+  }
+  if (struct_v >= 9) {
+    decode(stretch_mode_enabled, p);
+    decode(tiebreaker_mon, p);
+    decode(stretch_marked_down_mons, p);
+  } else {
+    stretch_mode_enabled = false;
+    tiebreaker_mon = "";
+    stretch_marked_down_mons.clear();
+  }
   calc_addr_mons();
   DECODE_FINISH(p);
 }
@@ -257,7 +324,7 @@ void MonMap::generate_test_instances(list<MonMap*>& o)
     entity_addrvec_t local_pub_addr;
     local_pub_addr.parse(local_pub_addr_s, &end_p);
 
-    m->add(mon_info_t("filled_pub_addr", entity_addrvec_t(local_pub_addr), 1));
+    m->add(mon_info_t("filled_pub_addr", entity_addrvec_t(local_pub_addr), 1, 1));
 
     m->add("empty_addr_zero", entity_addrvec_t());
   }
@@ -268,7 +335,7 @@ void MonMap::generate_test_instances(list<MonMap*>& o)
 int MonMap::write(const char *fn) 
 {
   // encode
-  bufferlist bl;
+  ceph::buffer::list bl;
   encode(bl, CEPH_FEATURES_ALL);
   
   return bl.write_file(fn);
@@ -277,7 +344,7 @@ int MonMap::write(const char *fn)
 int MonMap::read(const char *fn) 
 {
   // read
-  bufferlist bl;
+  ceph::buffer::list bl;
   std::string error;
   int r = bl.read_file(fn, &error);
   if (r < 0)
@@ -295,15 +362,13 @@ void MonMap::print_summary(ostream& out) const
   // mon_info_t instead. As such, print the map in a way
   // that keeps the expected format.
   bool has_printed = false;
-  for (map<string,mon_info_t>::const_iterator p = mon_info.begin();
-       p != mon_info.end();
-       ++p) {
+  for (auto p = mon_info.begin(); p != mon_info.end(); ++p) {
     if (has_printed)
       out << ",";
     out << p->first << "=" << p->second.public_addrs;
     has_printed = true;
   }
-  out << "}";
+  out << "}" << " removed_ranks: {" << removed_ranks << "}";
 }
  
 void MonMap::print(ostream& out) const
@@ -312,13 +377,26 @@ void MonMap::print(ostream& out) const
   out << "fsid " << fsid << "\n";
   out << "last_changed " << last_changed << "\n";
   out << "created " << created << "\n";
-  out << "min_mon_release " << (int)min_mon_release
-      << " (" << ceph_release_name(min_mon_release) << ")\n";
+  out << "min_mon_release " << to_integer<unsigned>(min_mon_release)
+      << " (" << min_mon_release << ")\n";
+  out << "election_strategy: " << strategy << "\n";
+  if (stretch_mode_enabled) {
+    out << "stretch_mode_enabled " << stretch_mode_enabled << "\n";
+    out << "tiebreaker_mon " << tiebreaker_mon << "\n";
+  }
+  if (stretch_mode_enabled ||
+      !disallowed_leaders.empty()) {
+    out << "disallowed_leaders " << disallowed_leaders << "\n";
+  }
   unsigned i = 0;
-  for (vector<string>::const_iterator p = ranks.begin();
-       p != ranks.end();
-       ++p) {
-    out << i++ << ": " << get_addrs(*p) << " mon." << *p << "\n";
+  for (auto p = ranks.begin(); p != ranks.end(); ++p) {
+    const auto &mi = mon_info.find(*p);
+    ceph_assert(mi != mon_info.end());
+    out << i++ << ": " << mi->second.public_addrs << " mon." << *p;
+    if (!mi->second.crush_loc.empty()) {
+      out << "; crush_location " << mi->second.crush_loc;
+    }
+    out << "\n";
   }
 }
 
@@ -326,19 +404,22 @@ void MonMap::dump(Formatter *f) const
 {
   f->dump_unsigned("epoch", epoch);
   f->dump_stream("fsid") <<  fsid;
-  f->dump_stream("modified") << last_changed;
-  f->dump_stream("created") << created;
-  f->dump_unsigned("min_mon_release", min_mon_release);
-  f->dump_string("min_mon_release_name", ceph_release_name(min_mon_release));
+  last_changed.gmtime(f->dump_stream("modified"));
+  created.gmtime(f->dump_stream("created"));
+  f->dump_unsigned("min_mon_release", to_integer<unsigned>(min_mon_release));
+  f->dump_string("min_mon_release_name", to_string(min_mon_release));
+  f->dump_int ("election_strategy", strategy);
+  f->dump_stream("disallowed_leaders: ") << disallowed_leaders;
+  f->dump_bool("stretch_mode", stretch_mode_enabled);
+  f->dump_string("tiebreaker_mon", tiebreaker_mon);
+  f->dump_stream("removed_ranks: ") << removed_ranks;
   f->open_object_section("features");
   persistent_features.dump(f, "persistent");
   optional_features.dump(f, "optional");
   f->close_section();
   f->open_array_section("mons");
   int i = 0;
-  for (vector<string>::const_iterator p = ranks.begin();
-       p != ranks.end();
-       ++p, ++i) {
+  for (auto p = ranks.begin(); p != ranks.end(); ++p, ++i) {
     f->open_object_section("mon");
     f->dump_int("rank", i);
     f->dump_string("name", *p);
@@ -346,26 +427,37 @@ void MonMap::dump(Formatter *f) const
     // compat: make these look like pre-nautilus entity_addr_t
     f->dump_stream("addr") << get_addrs(*p).get_legacy_str();
     f->dump_stream("public_addr") << get_addrs(*p).get_legacy_str();
+    f->dump_unsigned("priority", get_priority(*p));
+    f->dump_unsigned("weight", get_weight(*p));
+    const auto &mi = mon_info.find(*p);
+    // we don't need to assert this validity as all the get_* functions did
+    f->dump_stream("crush_location") << mi->second.crush_loc;
     f->close_section();
   }
   f->close_section();
 }
 
+void MonMap::dump_summary(Formatter *f) const
+{
+  f->dump_unsigned("epoch", epoch);
+  f->dump_string("min_mon_release_name", to_string(min_mon_release));
+  f->dump_unsigned("num_mons", ranks.size());
+}
+
 // an ambiguous mon addr may be legacy or may be msgr2--we aren' sure.
 // when that happens we need to try them both (unless we can
 // reasonably infer from the port number which it is).
 void MonMap::_add_ambiguous_addr(const string& name,
-                                entity_addr_t addr,
-                                int priority,
-                                bool for_mkfs)
+                                 entity_addr_t addr,
+                                 int priority,
+                                 int weight,
+                                 bool for_mkfs)
 {
   if (addr.get_type() != entity_addr_t::TYPE_ANY) {
     // a v1: or v2: prefix was specified
     if (addr.get_port() == 0) {
       // use default port
-      if (addr.get_type() == entity_addr_t::TYPE_ANY) {
-       addr.set_port(CEPH_MON_PORT_IANA);
-      } else if (addr.get_type() == entity_addr_t::TYPE_LEGACY) {
+      if (addr.get_type() == entity_addr_t::TYPE_LEGACY) {
        addr.set_port(CEPH_MON_PORT_LEGACY);
       } else if (addr.get_type() == entity_addr_t::TYPE_MSGR2) {
        addr.set_port(CEPH_MON_PORT_IANA);
@@ -374,11 +466,11 @@ void MonMap::_add_ambiguous_addr(const string& name,
        return;
       }
       if (!contains(addr)) {
-       add(name, entity_addrvec_t(addr));
+       add(name, entity_addrvec_t(addr), priority, weight);
       }
     } else {
       if (!contains(addr)) {
-       add(name, entity_addrvec_t(addr), priority);
+       add(name, entity_addrvec_t(addr), priority, weight);
       }
     }
   } else {
@@ -388,16 +480,16 @@ void MonMap::_add_ambiguous_addr(const string& name,
       addr.set_type(entity_addr_t::TYPE_LEGACY);
       if (!contains(addr)) {
        if (!for_mkfs) {
-         add(name + "-legacy", entity_addrvec_t(addr));
+         add(name + "-legacy", entity_addrvec_t(addr), priority, weight);
        } else {
-         add(name, entity_addrvec_t(addr));
+         add(name, entity_addrvec_t(addr), priority, weight);
        }
       }
     } else if (addr.get_port() == CEPH_MON_PORT_IANA) {
       // iana port implies msgr2 addr
       addr.set_type(entity_addr_t::TYPE_MSGR2);
       if (!contains(addr)) {
-       add(name, entity_addrvec_t(addr));
+       add(name, entity_addrvec_t(addr), priority, weight);
       }
     } else if (addr.get_port() == 0) {
       // no port; include both msgr2 and legacy ports
@@ -405,12 +497,12 @@ void MonMap::_add_ambiguous_addr(const string& name,
        addr.set_type(entity_addr_t::TYPE_MSGR2);
        addr.set_port(CEPH_MON_PORT_IANA);
        if (!contains(addr)) {
-         add(name, entity_addrvec_t(addr));
+         add(name, entity_addrvec_t(addr), priority, weight);
        }
        addr.set_type(entity_addr_t::TYPE_LEGACY);
        addr.set_port(CEPH_MON_PORT_LEGACY);
        if (!contains(addr)) {
-         add(name + "-legacy", entity_addrvec_t(addr));
+         add(name + "-legacy", entity_addrvec_t(addr), priority, weight);
        }
       } else {
        entity_addrvec_t av;
@@ -421,28 +513,46 @@ void MonMap::_add_ambiguous_addr(const string& name,
        addr.set_port(CEPH_MON_PORT_LEGACY);
        av.v.push_back(addr);
        if (!contains(av)) {
-         add(name, av);
+         add(name, av, priority, weight);
        }
       }
     } else {
       addr.set_type(entity_addr_t::TYPE_MSGR2);
       if (!contains(addr)) {
-       add(name, entity_addrvec_t(addr), priority);
+       add(name, entity_addrvec_t(addr), priority, weight);
       }
       if (!for_mkfs) {
        // try legacy on same port too
        addr.set_type(entity_addr_t::TYPE_LEGACY);
        if (!contains(addr)) {
-         add(name + "-legacy", entity_addrvec_t(addr), priority);
+         add(name + "-legacy", entity_addrvec_t(addr), priority, weight);
        }
       }
     }
   }
 }
 
+void MonMap::init_with_addrs(const std::vector<entity_addrvec_t>& addrs,
+                             bool for_mkfs,
+                             std::string_view prefix)
+{
+  char id = 'a';
+  for (auto& addr : addrs) {
+    string name{prefix};
+    name += id++;
+    if (addr.v.size() == 1) {
+      _add_ambiguous_addr(name, addr.front(), 0, 0, for_mkfs);
+    } else {
+      // they specified an addrvec, so let's assume they also specified
+      // the addr *type* and *port*.  (we could possibly improve this?)
+      add(name, addr, 0);
+    }
+  }
+}
+
 int MonMap::init_with_ips(const std::string& ips,
                          bool for_mkfs,
-                         const std::string &prefix)
+                         std::string_view prefix)
 {
   vector<entity_addrvec_t> addrs;
   if (!parse_ip_port_vec(
@@ -452,27 +562,13 @@ int MonMap::init_with_ips(const std::string& ips,
   }
   if (addrs.empty())
     return -ENOENT;
-  for (unsigned i=0; i<addrs.size(); i++) {
-    char n[2];
-    n[0] = 'a' + i;
-    n[1] = 0;
-    string name;
-    name = prefix;
-    name += n;
-    if (addrs[i].v.size() == 1) {
-      _add_ambiguous_addr(name, addrs[i].front(), 0, for_mkfs);
-    } else {
-      // they specified an addrvec, so let's assume they also specified
-      // the addr *type* and *port*.  (we could possibly improve this?)
-      add(name, addrs[i], 0);
-    }
-  }
+  init_with_addrs(addrs, for_mkfs, prefix);
   return 0;
 }
 
 int MonMap::init_with_hosts(const std::string& hostlist,
                            bool for_mkfs,
-                           const std::string& prefix)
+                           std::string_view prefix)
 {
   // maybe they passed us a DNS-resolvable name
   char *hosts = resolve_addrs(hostlist.c_str());
@@ -482,24 +578,13 @@ int MonMap::init_with_hosts(const std::string& hostlist,
   vector<entity_addrvec_t> addrs;
   bool success = parse_ip_port_vec(
     hosts, addrs,
-    for_mkfs ? entity_addr_t::TYPE_MSGR2 : entity_addr_t::TYPE_ANY);
+    entity_addr_t::TYPE_ANY);
   free(hosts);
   if (!success)
     return -EINVAL;
   if (addrs.empty())
     return -ENOENT;
-  for (unsigned i=0; i<addrs.size(); i++) {
-    char n[2];
-    n[0] = 'a' + i;
-    n[1] = 0;
-    string name = prefix;
-    name += n;
-    if (addrs[i].v.size() == 1) {
-      _add_ambiguous_addr(name, addrs[i].front(), 0);
-    } else {
-      add(name, addrs[i], 0);
-    }
-  }
+  init_with_addrs(addrs, for_mkfs, prefix);
   calc_legacy_ranks();
   return 0;
 }
@@ -593,7 +678,7 @@ int MonMap::init_with_config_file(const ConfigProxy& conf,
     // there on a weird port is a v1 address, and do not handle
     // addrvecs.
     entity_addr_t addr;
-    if (!addr.parse(val.c_str(), nullptr, entity_addr_t::TYPE_LEGACY)) {
+    if (!addr.parse(val, entity_addr_t::TYPE_LEGACY)) {
       errout << "unable to parse address for mon." << mon_name
              << ": addr='" << val << "'" << std::endl;
       continue;
@@ -611,29 +696,62 @@ int MonMap::init_with_config_file(const ConfigProxy& conf,
         continue;
       }
     }
+    uint16_t weight = 0;
+    if (!conf.get_val_from_conf_file(sections, "mon weight", val, false)) {
+      try {
+        weight = std::stoul(val);
+      } catch (std::logic_error&) {
+        errout << "unable to parse weight for mon." << mon_name
+               << ": weight='" << val << "'"
+               << std::endl;
+        continue;
+      }
+    }
 
-    // the make sure this mon isn't already in the map
+    // make sure this mon isn't already in the map
     if (contains(addr))
       remove(get_name(addr));
     if (contains(mon_name))
       remove(mon_name);
-    _add_ambiguous_addr(mon_name, addr, priority);
+    _add_ambiguous_addr(mon_name, addr, priority, weight, false);
   }
   return 0;
 }
 
-#ifdef WITH_SEASTAR
+void MonMap::check_health(health_check_map_t *checks) const
+{
+  if (stretch_mode_enabled) {
+    list<string> detail;
+    for (auto& p : mon_info) {
+      if (p.second.crush_loc.empty()) {
+       ostringstream ss;
+       ss << "mon " << p.first << " has no location set while in stretch mode";
+       detail.push_back(ss.str());
+      }
+    }
+    if (!detail.empty()) {
+      ostringstream ss;
+      ss << detail.size() << " monitor(s) have no location set while in stretch mode"
+        << "; this may cause issues with failover, OSD connections, netsplit handling, etc";
+      auto& d = checks->add("MON_LOCATION_NOT_SET", HEALTH_WARN,
+                           ss.str(), detail.size());
+      d.detail.swap(detail);
+    }
+  }
+}
 
-using namespace seastar;
+#ifdef WITH_SEASTAR
 
-future<> MonMap::read_monmap(const std::string& monmap)
+seastar::future<> MonMap::read_monmap(const std::string& monmap)
 {
+  using namespace seastar;
   return open_file_dma(monmap, open_flags::ro).then([this] (file f) {
     return f.size().then([this, f = std::move(f)](size_t s) {
       return do_with(make_file_input_stream(f), [this, s](input_stream<char>& in) {
         return in.read_exactly(s).then([this](temporary_buffer<char> buf) {
-          bufferlist bl;
-          bl.append(buffer::create(std::move(buf)));
+          ceph::buffer::list bl;
+          bl.push_back(ceph::buffer::ptr_node::create(
+            ceph::buffer::create(std::move(buf))));
           decode(bl);
         });
       });
@@ -641,8 +759,9 @@ future<> MonMap::read_monmap(const std::string& monmap)
   });
 }
 
-future<> MonMap::init_with_dns_srv(bool for_mkfs, const std::string& name)
+seastar::future<> MonMap::init_with_dns_srv(bool for_mkfs, const std::string& name)
 {
+  logger().debug("{}: for_mkfs={}, name={}", __func__, for_mkfs, name);
   string domain;
   string service = name;
   // check if domain is also provided and extract it from srv_name
@@ -651,12 +770,12 @@ future<> MonMap::init_with_dns_srv(bool for_mkfs, const std::string& name)
     domain = name.substr(idx + 1);
     service = name.substr(0, idx);
   }
-  return net::dns::get_srv_records(
-      net::dns_resolver::srv_proto::tcp,
-      service, domain).then([this](net::dns_resolver::srv_records records) {
-    return parallel_for_each(records, [this](auto record) {
-      return net::dns::resolve_name(record.target).then(
-          [record,this](net::inet_address a) {
+  return seastar::net::dns::get_srv_records(
+      seastar::net::dns_resolver::srv_proto::tcp,
+      service, domain).then([this](seastar::net::dns_resolver::srv_records records) {
+    return seastar::parallel_for_each(records, [this](auto record) {
+      return seastar::net::dns::resolve_name(record.target).then(
+          [record,this](seastar::net::inet_address a) {
        // the resolved address does not contain ceph specific info like nonce
        // nonce or msgr proto (legacy, msgr2), so set entity_addr_t manually
        entity_addr_t addr;
@@ -664,38 +783,56 @@ future<> MonMap::init_with_dns_srv(bool for_mkfs, const std::string& name)
        addr.set_family(int(a.in_family()));
        addr.set_port(record.port);
        switch (a.in_family()) {
-       case net::inet_address::family::INET:
+       case seastar::net::inet_address::family::INET:
          addr.in4_addr().sin_addr = a;
          break;
-       case net::inet_address::family::INET6:
+       case seastar::net::inet_address::family::INET6:
          addr.in6_addr().sin6_addr = a;
          break;
        }
-       _add_ambiguous_addr(record.target, addr, record.priority);
+        _add_ambiguous_addr(record.target,
+                            addr,
+                            record.priority,
+                            record.weight,
+                            false);
+      }).handle_exception_type([t=record.target](const std::system_error& e) {
+        logger().debug("{}: unable to resolve name for {}: {}",
+                       "init_with_dns_srv", t, e);
       });
     });
-  }).handle_exception_type([](const std::system_error& e) {
+  }).handle_exception_type([name](const std::system_error& e) {
+    logger().debug("{}: unable to get monitor info from DNS SRV with {}: {}",
+                 "init_with_dns_srv", name, e);
     // ignore DNS failures
     return seastar::make_ready_future<>();
   });
 }
 
-seastar::future<> MonMap::build_monmap(const ceph::common::ConfigProxy& conf,
-                                      bool for_mkfs)
+bool MonMap::maybe_init_with_mon_host(const std::string& mon_host,
+                                      const bool for_mkfs)
 {
-  // -m foo?
-  if (const auto mon_host = conf.get_val<std::string>("mon_host");
-      !mon_host.empty()) {
+  if (!mon_host.empty()) {
     if (auto ret = init_with_ips(mon_host, for_mkfs, "noname-"); ret == 0) {
-      return make_ready_future<>();
+      return true;
     }
     // TODO: resolve_addrs() is a blocking call
     if (auto ret = init_with_hosts(mon_host, for_mkfs, "noname-"); ret == 0) {
-      return make_ready_future<>();
+      return true;
     } else {
       throw std::runtime_error(cpp_strerror(ret));
     }
   }
+  return false;
+}
+
+seastar::future<> MonMap::build_monmap(const crimson::common::ConfigProxy& conf,
+                                      bool for_mkfs)
+{
+  logger().debug("{}: for_mkfs={}", __func__, for_mkfs);
+  // -m foo?
+  if (maybe_init_with_mon_host(conf.get_val<std::string>("mon_host"), for_mkfs)) {
+    return seastar::make_ready_future<>();
+  }
 
   // What monitors are in the config file?
   ostringstream errout;
@@ -703,7 +840,7 @@ seastar::future<> MonMap::build_monmap(const ceph::common::ConfigProxy& conf,
     throw std::runtime_error(errout.str());
   }
   if (size() > 0) {
-    return make_ready_future<>();
+    return seastar::make_ready_future<>();
   }
   // no info found from conf options lets try use DNS SRV records
   const string srv_name = conf.get_val<std::string>("mon_dns_srv_name");
@@ -714,8 +851,14 @@ seastar::future<> MonMap::build_monmap(const ceph::common::ConfigProxy& conf,
   });
 }
 
-future<> MonMap::build_initial(const ceph::common::ConfigProxy& conf, bool for_mkfs)
+seastar::future<> MonMap::build_initial(const crimson::common::ConfigProxy& conf, bool for_mkfs)
 {
+  // mon_host_override?
+  if (maybe_init_with_mon_host(conf.get_val<std::string>("mon_host_override"),
+                               for_mkfs)) {
+    return seastar::make_ready_future<>();
+  }
+
   // file?
   if (const auto monmap = conf.get_val<std::string>("monmap");
       !monmap.empty()) {
@@ -741,7 +884,7 @@ int MonMap::init_with_monmap(const std::string& monmap, std::ostream& errout)
   int r;
   try {
     r = read(monmap.c_str());
-  } catch (buffer::error&) {
+  } catch (ceph::buffer::error&) {
     r = -EINVAL;
   }
   if (r >= 0)
@@ -756,6 +899,8 @@ int MonMap::init_with_dns_srv(CephContext* cct,
                              bool for_mkfs,
                               std::ostream& errout)
 {
+  lgeneric_dout(cct, 1) << __func__ << " srv_name: " << srv_name << dendl;
+
   string domain;
   // check if domain is also provided and extract it from srv_name
   size_t idx = srv_name.find("_");
@@ -774,8 +919,11 @@ int MonMap::init_with_dns_srv(CephContext* cct,
   } else {
     for (auto& record : records) {
       record.second.addr.set_type(entity_addr_t::TYPE_ANY);
-      _add_ambiguous_addr(record.first, record.second.addr,
-                         record.second.priority);
+      _add_ambiguous_addr(record.first,
+                          record.second.addr,
+                          record.second.priority,
+                          record.second.weight,
+                          false);
     }
     return 0;
   }
@@ -783,7 +931,31 @@ int MonMap::init_with_dns_srv(CephContext* cct,
 
 int MonMap::build_initial(CephContext *cct, bool for_mkfs, ostream& errout)
 {
+  lgeneric_dout(cct, 1) << __func__ << " for_mkfs: " << for_mkfs << dendl;
   const auto& conf = cct->_conf;
+
+  // mon_host_override?
+  auto mon_host_override = conf.get_val<std::string>("mon_host_override");
+  if (!mon_host_override.empty()) {
+    lgeneric_dout(cct, 1) << "Using mon_host_override " << mon_host_override << dendl;
+    auto ret = init_with_ips(mon_host_override, for_mkfs, "noname-");
+    if (ret == -EINVAL) {
+      ret = init_with_hosts(mon_host_override, for_mkfs, "noname-");
+    }
+    if (ret < 0) {
+      errout << "unable to parse addrs in '" << mon_host_override << "'"
+            << std::endl;
+    }
+    return ret;
+  }
+
+  // cct?
+  auto addrs = cct->get_mon_addrs();
+  if (addrs != nullptr && (addrs->size() > 0)) {
+    init_with_addrs(*addrs, for_mkfs, "noname-");
+    return 0;
+  }
+
   // file?
   if (const auto monmap = conf.get_val<std::string>("monmap");
       !monmap.empty()) {
@@ -825,6 +997,7 @@ int MonMap::build_initial(CephContext *cct, bool for_mkfs, ostream& errout)
     errout << "no monitors specified to connect to." << std::endl;
     return -ENOENT;
   }
+  strategy = static_cast<election_strategy>(conf.get_val<uint64_t>("mon_election_default_strategy"));
   created = ceph_clock_now();
   last_changed = created;
   calc_legacy_ranks();