#include "librbd/internal.h"
#include "librbd/api/Mirror.h"
#include "tools/rbd_mirror/ClusterWatcher.h"
+#include "tools/rbd_mirror/ServiceDaemon.h"
#include "tools/rbd_mirror/types.h"
#include "test/rbd_mirror/test_fixture.h"
#include "test/librados/test.h"
{
m_cluster = std::make_shared<librados::Rados>();
EXPECT_EQ("", connect_cluster_pp(*m_cluster));
- m_cluster_watcher.reset(new ClusterWatcher(m_cluster, m_lock));
+ m_service_daemon.reset(new rbd::mirror::ServiceDaemon<>(g_ceph_context,
+ m_cluster));
+ m_cluster_watcher.reset(new ClusterWatcher(m_cluster, m_lock,
+ m_service_daemon.get()));
}
~TestClusterWatcher() override {
ASSERT_EQ(m_pool_peers, m_cluster_watcher->get_pool_peers());
}
- Mutex m_lock;
RadosRef m_cluster;
+ Mutex m_lock;
+ unique_ptr<rbd::mirror::ServiceDaemon<>> m_service_daemon;
unique_ptr<ClusterWatcher> m_cluster_watcher;
set<string> m_pools;
#include "cls/rbd/cls_rbd_client.h"
#include "tools/rbd_mirror/ImageDeleter.h"
#include "tools/rbd_mirror/ImageReplayer.h"
+#include "tools/rbd_mirror/ServiceDaemon.h"
#include "tools/rbd_mirror/Threads.h"
#include "librbd/ImageCtx.h"
#include "librbd/ImageState.h"
void SetUp() override {
TestFixture::SetUp();
+ m_service_daemon.reset(new rbd::mirror::ServiceDaemon<>(g_ceph_context,
+ _rados));
librbd::api::Mirror<>::mode_set(m_local_io_ctx, RBD_MIRROR_MODE_IMAGE);
m_deleter = new rbd::mirror::ImageDeleter<>(m_threads->work_queue,
m_threads->timer,
- &m_threads->timer_lock);
+ &m_threads->timer_lock,
+ m_service_daemon.get());
EXPECT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, 1 << 20));
ImageCtx *ictx = new ImageCtx(m_image_name, "", "", m_local_io_ctx,
librbd::RBD rbd;
std::string m_local_image_id;
+ std::unique_ptr<rbd::mirror::ServiceDaemon<>> m_service_daemon;
rbd::mirror::ImageDeleter<> *m_deleter;
};
#include "librbd/io/ImageRequestWQ.h"
#include "librbd/io/ReadResult.h"
#include "tools/rbd_mirror/types.h"
+#include "tools/rbd_mirror/ImageDeleter.h"
#include "tools/rbd_mirror/ImageReplayer.h"
#include "tools/rbd_mirror/InstanceWatcher.h"
+#include "tools/rbd_mirror/ServiceDaemon.h"
#include "tools/rbd_mirror/Threads.h"
-#include "tools/rbd_mirror/ImageDeleter.h"
#include "test/librados/test.h"
#include "gtest/gtest.h"
m_threads = new rbd::mirror::Threads<>(reinterpret_cast<CephContext*>(
m_local_ioctx.cct()));
+ m_service_daemon.reset(new rbd::mirror::ServiceDaemon<>(g_ceph_context,
+ m_local_cluster));
m_image_deleter.reset(new rbd::mirror::ImageDeleter<>(
- m_threads->work_queue, m_threads->timer, &m_threads->timer_lock));
+ m_threads->work_queue, m_threads->timer, &m_threads->timer_lock,
+ m_service_daemon.get()));
m_instance_watcher = rbd::mirror::InstanceWatcher<>::create(
m_local_ioctx, m_threads->work_queue, nullptr);
m_instance_watcher->handle_acquire_leader();
static int _image_number;
rbd::mirror::Threads<> *m_threads = nullptr;
+ unique_ptr<rbd::mirror::ServiceDaemon<>> m_service_daemon;
std::unique_ptr<rbd::mirror::ImageDeleter<>> m_image_deleter;
std::shared_ptr<librados::Rados> m_local_cluster;
librados::Rados m_remote_cluster;
#include "tools/rbd_mirror/ImageReplayer.h"
#include "tools/rbd_mirror/InstanceWatcher.h"
#include "tools/rbd_mirror/InstanceReplayer.h"
+#include "tools/rbd_mirror/ServiceDaemon.h"
#include "tools/rbd_mirror/Threads.h"
namespace librbd {
void(int64_t, const std::string&, Context*, bool));
};
+template<>
+struct ServiceDaemon<librbd::MockTestImageCtx> {
+};
+
template<>
struct InstanceWatcher<librbd::MockTestImageCtx> {
};
typedef ImageReplayer<librbd::MockTestImageCtx> MockImageReplayer;
typedef InstanceReplayer<librbd::MockTestImageCtx> MockInstanceReplayer;
typedef InstanceWatcher<librbd::MockTestImageCtx> MockInstanceWatcher;
+ typedef ServiceDaemon<librbd::MockTestImageCtx> MockServiceDaemon;
typedef Threads<librbd::MockTestImageCtx> MockThreads;
void SetUp() override {
};
TEST_F(TestMockInstanceReplayer, AcquireReleaseImage) {
+ MockServiceDaemon mock_service_daemon;
MockImageDeleter mock_image_deleter;
MockInstanceWatcher mock_instance_watcher;
MockImageReplayer mock_image_replayer;
MockInstanceReplayer instance_replayer(
- m_mock_threads, &mock_image_deleter,
+ m_mock_threads, &mock_service_daemon, &mock_image_deleter,
rbd::mirror::RadosRef(new librados::Rados(m_local_io_ctx)),
"local_mirror_uuid", m_local_io_ctx.get_id());
MirrorStatusWatcher.cc
PoolReplayer.cc
PoolWatcher.cc
+ ServiceDaemon.cc
Threads.cc
types.cc
image_replayer/BootstrapRequest.cc
namespace rbd {
namespace mirror {
-ClusterWatcher::ClusterWatcher(RadosRef cluster, Mutex &lock) :
- m_lock(lock),
- m_cluster(cluster)
+ClusterWatcher::ClusterWatcher(RadosRef cluster, Mutex &lock,
+ ServiceDaemon<librbd::ImageCtx>* service_daemon)
+ : m_cluster(cluster), m_lock(lock), m_service_daemon(service_daemon)
{
}
#include "include/rados/librados.hpp"
#include "types.h"
+namespace librbd { struct ImageCtx; }
+
namespace rbd {
namespace mirror {
+template <typename> class ServiceDaemon;
+
/**
* Tracks mirroring configuration for pools in a single
* cluster.
typedef std::map<int64_t, Peers> PoolPeers;
typedef std::set<std::string> PoolNames;
- ClusterWatcher(RadosRef cluster, Mutex &lock);
+ ClusterWatcher(RadosRef cluster, Mutex &lock,
+ ServiceDaemon<librbd::ImageCtx>* service_daemon);
~ClusterWatcher() = default;
ClusterWatcher(const ClusterWatcher&) = delete;
ClusterWatcher& operator=(const ClusterWatcher&) = delete;
const PoolPeers& get_pool_peers() const;
private:
- Mutex &m_lock;
RadosRef m_cluster;
+ Mutex &m_lock;
+ ServiceDaemon<librbd::ImageCtx>* m_service_daemon;
+
PoolPeers m_pool_peers;
void read_pool_peers(PoolPeers *pool_peers, PoolNames *pool_names);
template <typename I>
ImageDeleter<I>::ImageDeleter(ContextWQ *work_queue, SafeTimer *timer,
- Mutex *timer_lock)
- : m_running(true),
- m_work_queue(work_queue),
+ Mutex *timer_lock,
+ ServiceDaemon<librbd::ImageCtx>* service_daemon)
+ : m_work_queue(work_queue),
+ m_service_daemon(service_daemon),
m_delete_lock("rbd::mirror::ImageDeleter::Delete"),
m_image_deleter_thread(this),
m_failed_timer(timer),
namespace rbd {
namespace mirror {
+template <typename> class ServiceDaemon;
+
/**
* Manage deletion of non-primary images.
*/
public:
static const int EISPRM = 1000;
- ImageDeleter(ContextWQ *work_queue, SafeTimer *timer, Mutex *timer_lock);
+ ImageDeleter(ContextWQ *work_queue, SafeTimer *timer, Mutex *timer_lock,
+ ServiceDaemon<librbd::ImageCtx>* service_daemon);
~ImageDeleter();
ImageDeleter(const ImageDeleter&) = delete;
ImageDeleter& operator=(const ImageDeleter&) = delete;
bool print_failure_info=false);
};
- std::atomic<unsigned> m_running { 0 };
+ std::atomic<unsigned> m_running { 1 };
ContextWQ *m_work_queue;
+ ServiceDaemon<librbd::ImageCtx>* m_service_daemon;
std::deque<std::unique_ptr<DeleteInfo> > m_delete_queue;
Mutex m_delete_lock;
template <typename I>
InstanceReplayer<I>::InstanceReplayer(
- Threads<I> *threads, ImageDeleter<I>* image_deleter,
- RadosRef local_rados, const std::string &local_mirror_uuid,
- int64_t local_pool_id)
- : m_threads(threads), m_image_deleter(image_deleter),
- m_local_rados(local_rados), m_local_mirror_uuid(local_mirror_uuid),
- m_local_pool_id(local_pool_id),
+ Threads<I> *threads, ServiceDaemon<I>* service_daemon,
+ ImageDeleter<I>* image_deleter, RadosRef local_rados,
+ const std::string &local_mirror_uuid, int64_t local_pool_id)
+ : m_threads(threads), m_service_daemon(service_daemon),
+ m_image_deleter(image_deleter), m_local_rados(local_rados),
+ m_local_mirror_uuid(local_mirror_uuid), m_local_pool_id(local_pool_id),
m_lock("rbd::mirror::InstanceReplayer " + stringify(local_pool_id)) {
}
template <typename> class ImageDeleter;
template <typename> class ImageReplayer;
template <typename> class InstanceWatcher;
+template <typename> class ServiceDaemon;
template <typename> struct Threads;
template <typename ImageCtxT = librbd::ImageCtx>
public:
static InstanceReplayer* create(
Threads<ImageCtxT> *threads,
+ ServiceDaemon<ImageCtxT>* service_daemon,
ImageDeleter<ImageCtxT>* image_deleter,
RadosRef local_rados, const std::string &local_mirror_uuid,
int64_t local_pool_id) {
- return new InstanceReplayer(threads, image_deleter, local_rados,
- local_mirror_uuid, local_pool_id);
+ return new InstanceReplayer(threads, service_daemon, image_deleter,
+ local_rados, local_mirror_uuid, local_pool_id);
}
void destroy() {
delete this;
}
InstanceReplayer(Threads<ImageCtxT> *threads,
+ ServiceDaemon<ImageCtxT>* service_daemon,
ImageDeleter<ImageCtxT>* image_deleter,
RadosRef local_rados, const std::string &local_mirror_uuid,
int64_t local_pool_id);
typedef std::set<Peer> Peers;
Threads<ImageCtxT> *m_threads;
+ ServiceDaemon<ImageCtxT>* m_service_daemon;
ImageDeleter<ImageCtxT>* m_image_deleter;
RadosRef m_local_rados;
std::string m_local_mirror_uuid;
m_args(args),
m_lock("rbd::mirror::Mirror"),
m_local(new librados::Rados()),
+ m_service_daemon(m_cct, m_local),
m_asok_hook(new MirrorAdminSocketHook(cct, this))
{
cct->lookup_or_create_singleton_object<Threads<librbd::ImageCtx> >(
return r;
}
- m_local_cluster_watcher.reset(new ClusterWatcher(m_local, m_lock));
+ r = m_service_daemon.init();
+ if (r < 0) {
+ derr << "error registering service daemon: " << cpp_strerror(r) << dendl;
+ return r;
+ }
+
+ m_local_cluster_watcher.reset(new ClusterWatcher(m_local, m_lock,
+ &m_service_daemon));
m_image_deleter.reset(new ImageDeleter<>(m_threads->work_queue,
m_threads->timer,
- &m_threads->timer_lock));
-
+ &m_threads->timer_lock,
+ &m_service_daemon));
return r;
}
if (m_pool_replayers.find(pool_peer) == m_pool_replayers.end()) {
dout(20) << "starting pool replayer for " << peer << dendl;
unique_ptr<PoolReplayer> pool_replayer(new PoolReplayer(
- m_threads, m_image_deleter.get(), kv.first, peer, m_args));
+ m_threads, &m_service_daemon, m_image_deleter.get(), kv.first,
+ peer, m_args));
// TODO: make async, and retry connecting within pool replayer
int r = pool_replayer->init();
#include "PoolReplayer.h"
#include "ImageDeleter.h"
#include "types.h"
+#include "ServiceDaemon.h"
#include <set>
#include <map>
Mutex m_lock;
Cond m_cond;
RadosRef m_local;
+ ServiceDaemon<librbd::ImageCtx> m_service_daemon;
// monitor local cluster for config changes in peers
std::unique_ptr<ClusterWatcher> m_local_cluster_watcher;
} // anonymous namespace
PoolReplayer::PoolReplayer(Threads<librbd::ImageCtx> *threads,
+ ServiceDaemon<librbd::ImageCtx>* service_daemon,
ImageDeleter<>* image_deleter,
int64_t local_pool_id, const peer_t &peer,
const std::vector<const char*> &args) :
m_threads(threads),
+ m_service_daemon(service_daemon),
m_image_deleter(image_deleter),
m_lock(stringify("rbd::mirror::PoolReplayer ") + stringify(peer)),
m_peer(peer),
dout(20) << "connected to " << m_peer << dendl;
- m_instance_replayer.reset(
- InstanceReplayer<>::create(m_threads, m_image_deleter, m_local_rados,
- local_mirror_uuid, m_local_pool_id));
+ m_instance_replayer.reset(InstanceReplayer<>::create(
+ m_threads, m_service_daemon, m_image_deleter, m_local_rados,
+ local_mirror_uuid, m_local_pool_id));
m_instance_replayer->init();
m_instance_replayer->add_peer(m_peer.uuid, m_remote_io_ctx);
namespace rbd {
namespace mirror {
-template <typename> struct Threads;
template <typename> class InstanceReplayer;
template <typename> class InstanceWatcher;
+template <typename> class ServiceDaemon;
+template <typename> struct Threads;
/**
* Controls mirroring for a single remote cluster.
class PoolReplayer {
public:
PoolReplayer(Threads<librbd::ImageCtx> *threads,
+ ServiceDaemon<librbd::ImageCtx>* service_daemon,
ImageDeleter<>* image_deleter,
int64_t local_pool_id, const peer_t &peer,
const std::vector<const char*> &args);
void handle_update_leader(const std::string &leader_instance_id);
Threads<librbd::ImageCtx> *m_threads;
+ ServiceDaemon<librbd::ImageCtx>* m_service_daemon;
ImageDeleter<>* m_image_deleter;
mutable Mutex m_lock;
Cond m_cond;
--- /dev/null
+
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "tools/rbd_mirror/ServiceDaemon.h"
+#include "include/stringify.h"
+#include "common/ceph_context.h"
+#include "common/config.h"
+
+#define dout_context g_ceph_context
+#define dout_subsys ceph_subsys_rbd_mirror
+#undef dout_prefix
+#define dout_prefix *_dout << "rbd::mirror::ServiceDaemon: " << this << " " \
+ << __func__ << ": "
+
+namespace rbd {
+namespace mirror {
+
+namespace {
+
+const std::string RBD_MIRROR_AUTH_ID_PREFIX("rbd-mirror.");
+
+} // anonymous namespace
+
+template <typename I>
+int ServiceDaemon<I>::init() {
+ std::string name = m_cct->_conf->name.get_id();
+ if (name.find(RBD_MIRROR_AUTH_ID_PREFIX) == 0) {
+ name = name.substr(RBD_MIRROR_AUTH_ID_PREFIX.size());
+ }
+
+ std::map<std::string, std::string> service_metadata = {
+ {"instance_id", stringify(m_rados->get_instance_id())}
+ };
+ int r = m_rados->service_daemon_register("rbd-mirror", name,
+ service_metadata);
+ if (r < 0) {
+ return r;
+ }
+
+ return 0;
+}
+
+} // namespace mirror
+} // namespace rbd
+
+template class rbd::mirror::ServiceDaemon<librbd::ImageCtx>;
--- /dev/null
+
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#ifndef CEPH_RBD_MIRROR_SERVICE_DAEMON_H
+#define CEPH_RBD_MIRROR_SERVICE_DAEMON_H
+
+#include "tools/rbd_mirror/types.h"
+#include <string>
+
+struct CephContext;
+namespace librbd { struct ImageCtx; }
+
+namespace rbd {
+namespace mirror {
+
+template <typename ImageCtxT = librbd::ImageCtx>
+class ServiceDaemon {
+public:
+ ServiceDaemon(CephContext *cct, RadosRef rados)
+ : m_cct(cct), m_rados(rados) {
+ }
+
+ int init();
+
+private:
+ CephContext *m_cct;
+ RadosRef m_rados;
+
+};
+
+} // namespace mirror
+} // namespace rbd
+
+extern template class rbd::mirror::ServiceDaemon<librbd::ImageCtx>;
+
+#endif // CEPH_RBD_MIRROR_SERVICE_DAEMON_H