#include "common/PluginRegistry.h"
#include "common/valgrind.h"
#include "include/spinlock.h"
+#ifndef WITH_SEASTAR
+#include "mon/MonMap.h"
+#endif
using ceph::bufferlist;
using ceph::HeartbeatMap;
for (auto &&t : _fork_watchers)
t->handle_post_fork();
}
+
+void CephContext::set_mon_addrs(const MonMap& mm) {
+ std::vector<entity_addrvec_t> mon_addrs;
+ for (auto& i : mm.mon_info) {
+ mon_addrs.push_back(i.second.public_addrs);
+ }
+
+ set_mon_addrs(mon_addrs);
+}
#endif // WITH_SEASTAR
#include "common/cmdparse.h"
#include "common/code_environment.h"
+#include "msg/msg_types.h"
#ifdef WITH_SEASTAR
#include "crimson/common/config_proxy.h"
#include "crimson/common/perf_counters_collection.h"
class CephContextObs;
class CryptoHandler;
class CryptoRandom;
+class MonMap;
namespace ceph {
class PluginRegistry;
void notify_pre_fork();
void notify_post_fork();
+ /**
+ * update CephContext with a copy of the passed in MonMap mon addrs
+ *
+ * @param mm MonMap to extract and update mon addrs
+ */
+ void set_mon_addrs(const MonMap& mm);
+ void set_mon_addrs(const std::vector<entity_addrvec_t>& in) {
+ auto ptr = std::make_shared<std::vector<entity_addrvec_t>>(in);
+ atomic_store_explicit(&_mon_addrs, std::move(ptr), std::memory_order_relaxed);
+ }
+ std::shared_ptr<std::vector<entity_addrvec_t>> get_mon_addrs() const {
+ auto ptr = atomic_load_explicit(&_mon_addrs, std::memory_order_relaxed);
+ return ptr;
+ }
+
private:
int _crypto_inited;
+ std::shared_ptr<std::vector<entity_addrvec_t>> _mon_addrs;
+
/* libcommon service thread.
* SIGHUP wakes this thread, which then reopens logfiles */
friend class CephContextServiceThread;
}
}
+ cct->set_mon_addrs(monmap);
+
sub.got("monmap", monmap.get_epoch());
map_cond.Signal();
want_monmap = false;
}
}
+int
+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, 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);
+ }
+ }
+ return 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(
}
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);
- }
- }
- return 0;
+ return init_with_addrs(addrs, for_mkfs, prefix);
}
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());
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, 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);
- }
+ if (!init_with_addrs(addrs, for_mkfs, prefix)) {
+ return -EINVAL;
}
calc_legacy_ranks();
return 0;
int MonMap::build_initial(CephContext *cct, bool for_mkfs, ostream& errout)
{
const auto& conf = cct->_conf;
+
+ // cct?
+ auto addrs = cct->get_mon_addrs();
+ if (addrs != nullptr && (addrs->size() > 0)) {
+ return init_with_addrs(*addrs, for_mkfs, "noname-");
+ }
+
// file?
if (const auto monmap = conf.get_val<std::string>("monmap");
!monmap.empty()) {
static void generate_test_instances(list<MonMap*>& o);
protected:
+ /**
+ * build a monmap from a list of entity_addrvec_t's
+ *
+ * Give mons dummy names.
+ *
+ * @param addrs list of entity_addrvec_t's
+ * @param prefix prefix to prepend to generated mon names
+ * @return 0 for success, -errno on error
+ */
+ int init_with_addrs(const std::vector<entity_addrvec_t>& addrs,
+ bool for_mkfs,
+ std::string_view prefix);
/**
* build a monmap from a list of ips
*
*/
int init_with_ips(const std::string& ips,
bool for_mkfs,
- const std::string &prefix);
+ std::string_view prefix);
/**
* build a monmap from a list of hostnames
*
*/
int init_with_hosts(const std::string& hostlist,
bool for_mkfs,
- const std::string& prefix);
+ std::string_view prefix);
int init_with_config_file(const ConfigProxy& conf, std::ostream& errout);
#if WITH_SEASTAR
seastar::future<> read_monmap(const std::string& monmap);
acl.cc
main.cc
deleg.cc
+ monconfig.cc
)
target_link_libraries(ceph_test_libcephfs
ceph-common
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2020 Red Hat
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ */
+
+#include "gtest/gtest.h"
+#include "include/cephfs/libcephfs.h"
+#include "common/ceph_context.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+class MonConfig : public ::testing::Test
+{
+ protected:
+ struct ceph_mount_info *ca;
+
+ void SetUp() override {
+ ASSERT_EQ(0, ceph_create(&ca, NULL));
+ ASSERT_EQ(0, ceph_conf_read_file(ca, NULL));
+ ASSERT_EQ(0, ceph_conf_parse_env(ca, NULL));
+ }
+
+ void TearDown() override {
+ ceph_shutdown(ca);
+ }
+
+ // Helper to remove/unset all possible mon information from ConfigProxy
+ void clear_mon_config(CephContext *cct) {
+ auto& conf = cct->_conf;
+ // Clear safe_to_start_threads, allowing updates to config values
+ conf._clear_safe_to_start_threads();
+ ASSERT_EQ(0, conf.set_val("monmap", "", nullptr));
+ ASSERT_EQ(0, conf.set_val("mon_host", "", nullptr));
+ ASSERT_EQ(0, conf.set_val("mon_dns_srv_name", "", nullptr));
+ conf.set_safe_to_start_threads();
+ }
+
+ // Helper to test basic operation on a mount
+ void use_mount(struct ceph_mount_info *mnt, string name_prefix) {
+ char name[20];
+ snprintf(name, sizeof(name), "%s.%d", name_prefix.c_str(), getpid());
+ int fd = ceph_open(mnt, name, O_CREAT|O_RDWR, 0644);
+ ASSERT_LE(0, fd);
+
+ ceph_close(mnt, fd);
+ }
+};
+
+TEST_F(MonConfig, MonAddrsMissing) {
+ CephContext *cct;
+
+ // Test mount failure when there is no known mon config source
+ cct = ceph_get_mount_context(ca);
+ ASSERT_NE(nullptr, cct);
+ clear_mon_config(cct);
+
+ ASSERT_EQ(-ENOENT, ceph_mount(ca, NULL));
+}
+
+TEST_F(MonConfig, MonAddrsInConfigProxy) {
+ // Test a successful mount with default mon config source in ConfigProxy
+ ASSERT_EQ(0, ceph_mount(ca, NULL));
+
+ use_mount(ca, "foo");
+}
+
+TEST_F(MonConfig, MonAddrsInCct) {
+ struct ceph_mount_info *cb;
+ CephContext *cct;
+
+ // Perform mount to bootstrap mon addrs in CephContext
+ ASSERT_EQ(0, ceph_mount(ca, NULL));
+
+ // Reuse bootstrapped CephContext, clearing ConfigProxy mon addr sources
+ cct = ceph_get_mount_context(ca);
+ ASSERT_NE(nullptr, cct);
+ clear_mon_config(cct);
+ ASSERT_EQ(0, ceph_create_with_context(&cb, cct));
+
+ // Test a successful mount with only mon values in CephContext
+ ASSERT_EQ(0, ceph_mount(cb, NULL));
+
+ use_mount(ca, "bar");
+ use_mount(cb, "bar");
+
+ ceph_shutdown(cb);
+}