]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
rbd-mirror: extract optional peer mon_host/key values from MON
authorJason Dillaman <dillaman@redhat.com>
Mon, 10 Sep 2018 20:03:53 +0000 (16:03 -0400)
committerJason Dillaman <dillaman@redhat.com>
Wed, 12 Sep 2018 01:07:58 +0000 (21:07 -0400)
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/include/rbd_types.h
src/test/librbd/CMakeLists.txt
src/test/librbd/test_support.cc
src/test/librbd/test_support.h
src/test/rbd_mirror/CMakeLists.txt
src/test/rbd_mirror/test_ClusterWatcher.cc
src/test/rbd_mirror/test_LeaderWatcher.cc
src/tools/rbd_mirror/ClusterWatcher.cc
src/tools/rbd_mirror/ClusterWatcher.h
src/tools/rbd_mirror/Types.h

index 65135bf8657eb7c647e8ecdc3c70e2ad846aad89..0277fd923c37637d2f765e568be5e6f25cb5dd05 100644 (file)
 
 #define RBD_TRASH "rbd_trash"
 
+/**
+ * MON config-key prefix for storing optional remote cluster connectivity
+ * parameters
+ */
+#define RBD_MIRROR_PEER_CONFIG_KEY_PREFIX "rbd/mirror/peer/"
+
 struct rbd_info {
        __le64 max_id;
 } __attribute__ ((packed));
index 6b6b3b99c89a8dad5a309fd41ce646e1355bf67f..99f7e7dfd647de9af92c10ab43431b26c0c73a45 100644 (file)
@@ -1,6 +1,12 @@
+set(librbd_test_support_srcs
+  test_support.cc
+  )
+add_library(rbd_test_support STATIC ${librbd_test_support_srcs})
+target_link_libraries(rbd_test_support PRIVATE
+  GTest::GTest)
+
 set(librbd_test
   test_fixture.cc
-  test_support.cc
   test_librbd.cc
   test_ImageWatcher.cc
   test_internal.cc
@@ -16,6 +22,7 @@ set(librbd_test
   journal/test_Replay.cc)
 add_library(rbd_test STATIC ${librbd_test})
 target_link_libraries(rbd_test PRIVATE
+  rbd_test_support
   Boost::thread
   GMock::GMock
   GTest::GTest)
index 55ebe03dce32d6bf00305b88c6fa39055279107e..b0eb932e9830aa03ee55bb83e71f2c683d48c755 100644 (file)
@@ -2,6 +2,7 @@
 // vim: ts=8 sw=2 smarttab
 #include "test/librbd/test_support.h"
 #include "include/rbd_types.h"
+#include "gtest/gtest.h"
 #include <sstream>
 
 bool get_features(uint64_t *features) {
@@ -118,3 +119,10 @@ int create_image_data_pool(librados::Rados &rados, std::string &data_pool, bool
 
   return r;
 }
+
+bool is_librados_test_stub(librados::Rados &rados) {
+  std::string fsid;
+  EXPECT_EQ(0, rados.cluster_fsid(&fsid));
+  return fsid == "00000000-1111-2222-3333-444444444444";
+}
+
index 47707b1c015690934e700a8adbcc2450f7eda70b..abb7c4702cd197144691ae60343cd5730ca3383d 100644 (file)
@@ -24,6 +24,8 @@ int clone_image_pp(librbd::RBD &rbd, librbd::Image &p_image, librados::IoCtx &p_
 int get_image_id(librbd::Image &image, std::string *image_id);
 int create_image_data_pool(librados::Rados &rados, std::string &data_pool, bool *created);
 
+bool is_librados_test_stub(librados::Rados &rados);
+
 #define REQUIRE(x) {                     \
   if (!(x)) {                            \
     std::cout << "SKIPPING" << std::endl; \
index b9ecbb1beafc600376888ba61858ee3365619ca1..3346f08c35a0fbbadd5a30fe793e3426137d8ddc 100644 (file)
@@ -12,6 +12,7 @@ set(rbd_mirror_test_srcs
   )
 add_library(rbd_mirror_test STATIC ${rbd_mirror_test_srcs})
 target_link_libraries(rbd_mirror_test
+  rbd_test_support
   GTest::GTest)
 
 add_executable(unittest_rbd_mirror
index 0300bc183959bac3c285ed8c98aa9f7e5c10f953..a69085cc12e1b5260050b1bfef164d0ad5bc6b04 100644 (file)
@@ -11,6 +11,7 @@
 #include "tools/rbd_mirror/Types.h"
 #include "test/rbd_mirror/test_fixture.h"
 #include "test/librados/test.h"
+#include "test/librbd/test_support.h"
 #include "gtest/gtest.h"
 #include <boost/scope_exit.hpp>
 #include <iostream>
@@ -102,6 +103,27 @@ public:
     ASSERT_EQ(0, m_cluster->pool_delete(name.c_str()));
   }
 
+  void set_peer_config_key(const std::string& pool_name,
+                           const PeerSpec &peer) {
+    int64_t pool_id = m_cluster->pool_lookup(pool_name.c_str());
+    ASSERT_GE(pool_id, 0);
+
+    std::string json =
+      "{"
+        "\\\"mon_host\\\": \\\"" + peer.mon_host + "\\\", "
+        "\\\"key\\\": \\\"" + peer.key + "\\\""
+      "}";
+
+    bufferlist in_bl;
+    ASSERT_EQ(0, m_cluster->mon_command(
+      "{"
+        "\"prefix\": \"config-key set\","
+        "\"key\": \"" RBD_MIRROR_PEER_CONFIG_KEY_PREFIX + stringify(pool_id) +
+          "/" + peer.uuid + "\","
+        "\"val\": \"" + json + "\"" +
+      "}", in_bl, nullptr, nullptr));
+  }
+
   void create_cache_pool(const string &base_pool, string *cache_pool_name) {
     bufferlist inbl;
     *cache_pool_name = get_temp_pool_name("test-rbd-mirror-");
@@ -211,3 +233,22 @@ TEST_F(TestClusterWatcher, CachePools) {
   } BOOST_SCOPE_EXIT_END;
   check_peers();
 }
+
+TEST_F(TestClusterWatcher, ConfigKey) {
+  REQUIRE(!is_librados_test_stub(*m_cluster));
+
+  std::string pool_name;
+  check_peers();
+
+  PeerSpec site1("", "site1", "mirror1");
+  create_pool(true, site1, &site1.uuid, &pool_name);
+  check_peers();
+
+  PeerSpec site2("", "site2", "mirror2");
+  site2.mon_host = "abc";
+  site2.key = "xyz";
+  create_pool(false, site2, &site2.uuid);
+  set_peer_config_key(pool_name, site2);
+
+  check_peers();
+}
index 490c07ab4e5cc9c2bbe347c0f69588b479344e3c..63118ebfe4f59bf44daf363ffe5f43de0c006921 100644 (file)
@@ -101,19 +101,13 @@ public:
     EXPECT_EQ(0, librbd::api::Mirror<>::mode_set(m_local_io_ctx,
                                                  RBD_MIRROR_MODE_POOL));
 
-    if (is_librados_test_stub()) {
+    if (is_librados_test_stub(*_rados)) {
       // speed testing up a little
       EXPECT_EQ(0, _rados->conf_set("rbd_mirror_leader_heartbeat_interval",
                                     "1"));
     }
   }
 
-  bool is_librados_test_stub() {
-    std::string fsid;
-    EXPECT_EQ(0, _rados->cluster_fsid(&fsid));
-    return fsid == "00000000-1111-2222-3333-444444444444";
-  }
-
   librados::IoCtx &create_connection(bool no_heartbeats = false) {
     m_connections.push_back(std::unique_ptr<Connection>(new Connection()));
     Connection *c = m_connections.back().get();
@@ -122,7 +116,7 @@ public:
     if (no_heartbeats) {
       EXPECT_EQ(0, c->cluster.conf_set("rbd_mirror_leader_heartbeat_interval",
                                        "3600"));
-    } else if (is_librados_test_stub()) {
+    } else if (is_librados_test_stub(*_rados)) {
       EXPECT_EQ(0, c->cluster.conf_set("rbd_mirror_leader_heartbeat_interval",
                                        "1"));
     }
index bff1b2304d388f8ca7ce42d8cbcc989c4cab08ea..54329de63792ead05f2207fae796d44c060bdd64 100644 (file)
@@ -2,6 +2,8 @@
 // vim: ts=8 sw=2 smarttab
 
 #include "ClusterWatcher.h"
+#include "include/stringify.h"
+#include "common/ceph_json.h"
 #include "common/debug.h"
 #include "common/errno.h"
 #include "cls/rbd/cls_rbd_client.h"
@@ -135,12 +137,20 @@ void ClusterWatcher::read_pool_peers(PoolPeers *pool_peers)
       continue;
     }
 
+    std::vector<PeerSpec> peers{configs.begin(), configs.end()};
+    for (auto& peer : peers) {
+      r = resolve_peer_config_keys(pool_id, pool_name, &peer);
+      if (r < 0) {
+        break;
+      }
+    }
+
     if (m_service_pools[pool_id] != service_daemon::CALLOUT_ID_NONE) {
       m_service_daemon->remove_callout(pool_id, m_service_pools[pool_id]);
       m_service_pools[pool_id] = service_daemon::CALLOUT_ID_NONE;
     }
 
-    pool_peers->insert({pool_id, Peers{configs.begin(), configs.end()}});
+    pool_peers->emplace(pool_id, Peers{peers.begin(), peers.end()});
   }
 
   for (auto it = m_service_pools.begin(); it != m_service_pools.end(); ) {
@@ -152,5 +162,62 @@ void ClusterWatcher::read_pool_peers(PoolPeers *pool_peers)
   }
 }
 
+int ClusterWatcher::resolve_peer_config_keys(int64_t pool_id,
+                                             const std::string& pool_name,
+                                             PeerSpec* peer) {
+  dout(10) << "retrieving config-key: pool_id=" << pool_id << ", "
+           << "pool_name=" << pool_name << ", "
+           << "peer_uuid=" << peer->uuid << dendl;
+
+  std::string cmd =
+    "{"
+      "\"prefix\": \"config-key get\", "
+      "\"key\": \"" RBD_MIRROR_PEER_CONFIG_KEY_PREFIX + stringify(pool_id) +
+        "/" + peer->uuid + "\""
+    "}";
+
+  bufferlist in_bl;
+  bufferlist out_bl;
+  int r = m_cluster->mon_command(cmd, in_bl, &out_bl, nullptr);
+  if (r == -ENOENT || out_bl.length() == 0) {
+    return 0;
+  } else if (r < 0) {
+    derr << "error reading mirroring peer config for pool " << pool_name << ": "
+         << cpp_strerror(r) << dendl;
+    m_service_pools[pool_id] = m_service_daemon->add_or_update_callout(
+      pool_id, m_service_pools[pool_id],
+      service_daemon::CALLOUT_LEVEL_WARNING,
+      "mirroring peer config-key query failed");
+    return r;
+  }
+
+  bool json_valid = false;
+  json_spirit::mValue json_root;
+  if(json_spirit::read(out_bl.to_str(), json_root)) {
+    try {
+      auto& json_obj = json_root.get_obj();
+      if (json_obj.count("mon_host")) {
+        peer->mon_host = json_obj["mon_host"].get_str();
+      }
+      if (json_obj.count("key")) {
+        peer->key = json_obj["key"].get_str();
+      }
+      json_valid = true;
+    } catch (std::runtime_error&) {
+    }
+  }
+
+  if (!json_valid) {
+    derr << "error parsing mirroring peer config for pool " << pool_name << ", "
+         << "peer " << peer->uuid << dendl;
+    m_service_pools[pool_id] = m_service_daemon->add_or_update_callout(
+      pool_id, m_service_pools[pool_id],
+      service_daemon::CALLOUT_LEVEL_WARNING,
+      "mirroring peer config-key decode failed");
+  }
+
+  return 0;
+}
+
 } // namespace mirror
 } // namespace rbd
index 9941d15c9ca2516227c96716304f5a134b37076f..e8430b476ce96a46c3d2550e9e585d0751497307 100644 (file)
@@ -29,7 +29,12 @@ template <typename> class ServiceDaemon;
  */
 class ClusterWatcher {
 public:
-  typedef std::set<PeerSpec> Peers;
+  struct PeerSpecCompare {
+    bool operator()(const PeerSpec& lhs, const PeerSpec& rhs) const {
+      return (lhs.uuid < rhs.uuid);
+    }
+  };
+  typedef std::set<PeerSpec, PeerSpecCompare> Peers;
   typedef std::map<int64_t, Peers>  PoolPeers;
 
   ClusterWatcher(RadosRef cluster, Mutex &lock,
@@ -53,6 +58,9 @@ private:
   PoolPeers m_pool_peers;
 
   void read_pool_peers(PoolPeers *pool_peers);
+
+  int resolve_peer_config_keys(int64_t pool_id, const std::string& pool_name,
+                               PeerSpec* peer);
 };
 
 } // namespace mirror
index 6fbd95f4ee1b86801bfd25a752b751e04ec6665d..23ec5e291ea509d6fb503bdfb5553e6851855b74 100644 (file)
@@ -79,11 +79,29 @@ struct PeerSpec {
   std::string cluster_name;
   std::string client_name;
 
-  bool operator<(const PeerSpec &rhs) const {
-    return uuid < rhs.uuid;
+  /// optional config properties
+  std::string mon_host;
+  std::string key;
+
+  bool operator==(const PeerSpec& rhs) const {
+    return (uuid == rhs.uuid &&
+            cluster_name == rhs.cluster_name &&
+            client_name == rhs.client_name &&
+            mon_host == rhs.mon_host &&
+            key == rhs.key);
   }
-  bool operator==(const PeerSpec &rhs) const {
-    return uuid == rhs.uuid;
+  bool operator<(const PeerSpec& rhs) const {
+    if (uuid != rhs.uuid) {
+      return uuid < rhs.uuid;
+    } else if (cluster_name != rhs.cluster_name) {
+      return cluster_name < rhs.cluster_name;
+    } else if (client_name != rhs.client_name) {
+      return client_name < rhs.client_name;
+    } else if (mon_host < rhs.mon_host) {
+      return mon_host < rhs.mon_host;
+    } else {
+      return key < rhs.key;
+    }
   }
 };