template<>
struct ServiceDaemon<librbd::MockTestImageCtx> {
- MOCK_METHOD3(add_or_update_attribute,
- void(int64_t, const std::string&,
+ MOCK_METHOD4(add_or_update_namespace_attribute,
+ void(int64_t, const std::string&, const std::string&,
const service_daemon::AttributeValue&));
};
EXPECT_CALL(mock_image_replayer, is_blacklisted()).WillOnce(Return(false));
EXPECT_CALL(mock_image_replayer, is_finished()).WillOnce(Return(true));
EXPECT_CALL(mock_image_replayer, destroy());
- EXPECT_CALL(mock_service_daemon,add_or_update_attribute(_, _, _)).Times(3);
+ EXPECT_CALL(mock_service_daemon,
+ add_or_update_namespace_attribute(_, _, _, _)).Times(3);
ASSERT_TRUE(start_image_replayers_ctx != nullptr);
start_image_replayers_ctx->complete(0);
template<>
struct ServiceDaemon<librbd::MockTestImageCtx> {
- MOCK_METHOD3(add_or_update_attribute,
- void(int64_t, const std::string&,
+ MOCK_METHOD4(add_or_update_namespace_attribute,
+ void(int64_t, const std::string&, const std::string&,
const service_daemon::AttributeValue&));
MOCK_METHOD2(remove_attribute,
void(int64_t, const std::string&));
.WillOnce(CompleteContext(m_mock_threads->work_queue, 0));
}
- void expect_service_daemon_add_or_update_attribute(
- MockServiceDaemon &mock_service_daemon, const std::string& key,
- const service_daemon::AttributeValue& value) {
- EXPECT_CALL(mock_service_daemon, add_or_update_attribute(_, key, value));
- }
-
- void expect_service_daemon_add_or_update_instance_id_attribute(
- MockInstanceWatcher &mock_instance_watcher,
- MockServiceDaemon &mock_service_daemon) {
- expect_instance_watcher_get_instance_id(mock_instance_watcher, "1234");
- expect_service_daemon_add_or_update_attribute(
- mock_service_daemon, "instance_id", {std::string("1234")});
- }
-
MockThreads *m_mock_threads;
};
expect_instance_watcher_init(*mock_instance_watcher, 0);
MockServiceDaemon mock_service_daemon;
- expect_service_daemon_add_or_update_instance_id_attribute(
- *mock_instance_watcher, mock_service_daemon);
-
MockNamespaceReplayer namespace_replayer(
{}, m_local_io_ctx, m_remote_io_ctx, "local mirror uuid",
"remote mirror uuid", "siteA", m_mock_threads, nullptr, nullptr,
expect_instance_watcher_init(*mock_instance_watcher, 0);
MockServiceDaemon mock_service_daemon;
- expect_service_daemon_add_or_update_instance_id_attribute(
- *mock_instance_watcher, mock_service_daemon);
-
MockNamespaceReplayer namespace_replayer(
{}, m_local_io_ctx, m_remote_io_ctx, "local mirror uuid",
"remote mirror uuid", "siteA", m_mock_threads, nullptr, nullptr,
template<>
struct ServiceDaemon<librbd::MockTestImageCtx> {
+ MOCK_METHOD2(add_namespace, void(int64_t, const std::string &));
+ MOCK_METHOD2(remove_namespace, void(int64_t, const std::string &));
+
MOCK_METHOD3(add_or_update_attribute,
void(int64_t, const std::string&,
const service_daemon::AttributeValue&));
EXPECT_CALL(mock_namespace_replayer, handle_instances_removed(_));
}
+ void expect_service_daemon_add_namespace(
+ MockServiceDaemon &mock_service_daemon,
+ const std::string& namespace_name) {
+ EXPECT_CALL(mock_service_daemon,
+ add_namespace(m_local_io_ctx.get_id(), namespace_name));
+ }
+
+ void expect_service_daemon_remove_namespace(
+ MockServiceDaemon &mock_service_daemon,
+ const std::string& namespace_name) {
+ EXPECT_CALL(mock_service_daemon,
+ remove_namespace(m_local_io_ctx.get_id(), namespace_name));
+ }
+
void expect_service_daemon_add_or_update_attribute(
MockServiceDaemon &mock_service_daemon, const std::string& key,
const service_daemon::AttributeValue& value) {
MockServiceDaemon &mock_service_daemon, const std::string& key) {
EXPECT_CALL(mock_service_daemon, remove_attribute(_, key));
}
+
+ void expect_service_daemon_add_or_update_instance_id_attribute(
+ MockServiceDaemon &mock_service_daemon, const std::string &instance_id) {
+ expect_service_daemon_add_or_update_attribute(
+ mock_service_daemon, "instance_id", {instance_id});
+ }
};
TEST_F(TestMockPoolReplayer, ConfigKeyOverride) {
expect_leader_watcher_init(*mock_leader_watcher, 0);
MockServiceDaemon mock_service_daemon;
+ std::string instance_id = stringify(mock_local_io_ctx->get_instance_id());
+ expect_service_daemon_add_or_update_instance_id_attribute(
+ mock_service_daemon, instance_id);
+
MockPoolReplayer pool_replayer(&mock_threads, &mock_service_daemon, nullptr,
m_local_io_ctx.get_id(), peer_spec, {});
pool_replayer.init("siteA");
expect_leader_watcher_init(*mock_leader_watcher, 0);
MockServiceDaemon mock_service_daemon;
+ std::string instance_id = stringify(mock_local_io_ctx->get_instance_id());
+ expect_service_daemon_add_or_update_instance_id_attribute(
+ mock_service_daemon, instance_id);
+
MockPoolReplayer pool_replayer(&mock_threads, &mock_service_daemon, nullptr,
m_local_io_ctx.get_id(), peer_spec, {});
pool_replayer.init("siteA");
expect_leader_watcher_init(*mock_leader_watcher, 0);
MockServiceDaemon mock_service_daemon;
+ std::string instance_id = stringify(mock_local_io_ctx->get_instance_id());
+ expect_service_daemon_add_or_update_instance_id_attribute(
+ mock_service_daemon, instance_id);
+
MockPoolReplayer pool_replayer(&mock_threads, &mock_service_daemon, nullptr,
m_local_io_ctx.get_id(), peer_spec, {});
pool_replayer.init("siteA");
C_SaferCond on_ns1_init;
expect_namespace_replayer_init(*mock_ns1_namespace_replayer, 0);
+ expect_service_daemon_add_namespace(mock_service_daemon, "ns1");
expect_namespace_replayer_handle_update_leader(*mock_ns1_namespace_replayer,
"", &on_ns1_init);
ASSERT_EQ(0, on_acquire.wait());
expect_namespace_replayer_init(*mock_ns2_namespace_replayer, 0);
+ expect_service_daemon_add_namespace(mock_service_daemon, "ns2");
C_SaferCond on_ns2_acquire;
expect_namespace_replayer_handle_acquire_leader(
*mock_ns2_namespace_replayer, 0, &on_ns2_acquire);
ASSERT_EQ(0, on_ns2_acquire.wait());
C_SaferCond on_ns2_shut_down;
+ expect_service_daemon_remove_namespace(mock_service_daemon, "ns2");
expect_namespace_replayer_shut_down(*mock_ns2_namespace_replayer,
&on_ns2_shut_down);
mock_namespace.remove("ns2");
mock_leader_watcher->listener->pre_release_handler(&on_release);
ASSERT_EQ(0, on_release.wait());
+ expect_service_daemon_remove_namespace(mock_service_daemon, "ns1");
expect_namespace_replayer_shut_down(*mock_ns1_namespace_replayer);
expect_leader_watcher_shut_down(*mock_leader_watcher);
expect_namespace_replayer_shut_down(*mock_default_namespace_replayer);
expect_leader_watcher_init(*mock_leader_watcher, 0);
MockServiceDaemon mock_service_daemon;
+ std::string instance_id = stringify(mock_local_io_ctx->get_instance_id());
+ expect_service_daemon_add_or_update_instance_id_attribute(
+ mock_service_daemon, instance_id);
+
MockPoolReplayer pool_replayer(&mock_threads, &mock_service_daemon, nullptr,
m_local_io_ctx.get_id(), peer_spec, {});
pool_replayer.init("siteA");
C_SaferCond on_ns2_init;
expect_namespace_replayer_init(*mock_ns2_namespace_replayer, 0);
+ expect_service_daemon_add_namespace(mock_service_daemon, "ns2");
expect_namespace_replayer_handle_update_leader(*mock_ns2_namespace_replayer,
"", &on_ns2_init);
mock_namespace.add("ns2");
ASSERT_EQ(0, on_ns2_init.wait());
-
+
expect_service_daemon_add_or_update_attribute(
mock_service_daemon, SERVICE_DAEMON_LEADER_KEY, true);
expect_namespace_replayer_handle_acquire_leader(
[&mock_namespace](int) {
mock_namespace.remove("ns2");
});
+ expect_service_daemon_remove_namespace(mock_service_daemon, "ns2");
expect_namespace_replayer_shut_down(*mock_ns2_namespace_replayer, ctx);
mock_namespace.add("ns2");
on_ns3_shut_down.complete(0);
});
expect_namespace_replayer_init(*mock_ns3_namespace_replayer, 0);
+ expect_service_daemon_add_namespace(mock_service_daemon, "ns3");
expect_namespace_replayer_handle_acquire_leader(*mock_ns3_namespace_replayer,
-EINVAL);
+ expect_service_daemon_remove_namespace(mock_service_daemon, "ns3");
expect_namespace_replayer_shut_down(*mock_ns3_namespace_replayer, ctx);
mock_namespace.add("ns3");
ASSERT_EQ(0, on_ns3_shut_down.wait());
start_image_replayer(current_it->second);
}
- // TODO: add namespace support to service daemon
- if (m_local_io_ctx.get_namespace().empty()) {
- m_service_daemon->add_or_update_attribute(
- m_local_io_ctx.get_id(), SERVICE_DAEMON_ASSIGNED_COUNT_KEY, image_count);
- m_service_daemon->add_or_update_attribute(
- m_local_io_ctx.get_id(), SERVICE_DAEMON_WARNING_COUNT_KEY, warning_count);
- m_service_daemon->add_or_update_attribute(
- m_local_io_ctx.get_id(), SERVICE_DAEMON_ERROR_COUNT_KEY, error_count);
- }
+ m_service_daemon->add_or_update_namespace_attribute(
+ m_local_io_ctx.get_id(), m_local_io_ctx.get_namespace(),
+ SERVICE_DAEMON_ASSIGNED_COUNT_KEY, image_count);
+ m_service_daemon->add_or_update_namespace_attribute(
+ m_local_io_ctx.get_id(), m_local_io_ctx.get_namespace(),
+ SERVICE_DAEMON_WARNING_COUNT_KEY, warning_count);
+ m_service_daemon->add_or_update_namespace_attribute(
+ m_local_io_ctx.get_id(), m_local_io_ctx.get_namespace(),
+ SERVICE_DAEMON_ERROR_COUNT_KEY, error_count);
m_async_op_tracker.finish_op();
}
namespace {
-const std::string SERVICE_DAEMON_INSTANCE_ID_KEY("instance_id");
const std::string SERVICE_DAEMON_LOCAL_COUNT_KEY("image_local_count");
const std::string SERVICE_DAEMON_REMOTE_COUNT_KEY("image_remote_count");
<< "added_count=" << added_image_ids.size() << ", "
<< "removed_count=" << removed_image_ids.size() << dendl;
- // TODO: add namespace support to service daemon
- if (m_local_io_ctx.get_namespace().empty()) {
- m_service_daemon->add_or_update_attribute(
- m_local_io_ctx.get_id(), SERVICE_DAEMON_LOCAL_COUNT_KEY,
- m_local_pool_watcher->get_image_count());
- if (m_remote_pool_watcher) {
- m_service_daemon->add_or_update_attribute(
- m_local_io_ctx.get_id(), SERVICE_DAEMON_REMOTE_COUNT_KEY,
- m_remote_pool_watcher->get_image_count());
- }
+ m_service_daemon->add_or_update_namespace_attribute(
+ m_local_io_ctx.get_id(), m_local_io_ctx.get_namespace(),
+ SERVICE_DAEMON_LOCAL_COUNT_KEY, m_local_pool_watcher->get_image_count());
+ if (m_remote_pool_watcher) {
+ m_service_daemon->add_or_update_namespace_attribute(
+ m_local_io_ctx.get_id(), m_local_io_ctx.get_namespace(),
+ SERVICE_DAEMON_REMOTE_COUNT_KEY,
+ m_remote_pool_watcher->get_image_count());
}
std::set<std::string> added_global_image_ids;
return;
}
- // TODO: add namespace support to service daemon
- if (m_local_io_ctx.get_namespace().empty()) {
- m_service_daemon->add_or_update_attribute(
- m_local_io_ctx.get_id(), SERVICE_DAEMON_INSTANCE_ID_KEY,
- m_instance_watcher->get_instance_id());
- }
-
ceph_assert(m_on_finish != nullptr);
m_threads->work_queue->queue(m_on_finish);
m_on_finish = nullptr;
namespace {
+const std::string SERVICE_DAEMON_INSTANCE_ID_KEY("instance_id");
const std::string SERVICE_DAEMON_LEADER_KEY("leader");
const std::vector<std::string> UNIQUE_PEER_CONFIG_KEYS {
m_callout_id = service_daemon::CALLOUT_ID_NONE;
}
+ m_service_daemon->add_or_update_attribute(
+ m_local_io_ctx.get_id(), SERVICE_DAEMON_INSTANCE_ID_KEY,
+ stringify(m_local_io_ctx.get_instance_id()));
+
m_pool_replayer_thread.create("pool replayer");
}
delete namespace_replayer;
ctx->complete(r);
});
+ m_service_daemon->remove_namespace(m_local_pool_id, it->first);
namespace_replayer->shut_down(on_shut_down);
it = m_namespace_replayers.erase(it);
} else {
} else {
std::lock_guard locker{m_lock};
m_namespace_replayers[name] = namespace_replayer;
+ m_service_daemon->add_namespace(m_local_pool_id, name);
}
ctx->complete(r);
});
delete namespace_replayer;
on_finish->complete(r);
});
+ m_service_daemon->remove_namespace(m_local_pool_id, name);
namespace_replayer->shut_down(on_shut_down);
return;
}
schedule_update_status();
}
+template <typename I>
+void ServiceDaemon<I>::add_namespace(int64_t pool_id,
+ const std::string& namespace_name) {
+ dout(20) << "pool_id=" << pool_id << ", namespace=" << namespace_name
+ << dendl;
+
+ std::lock_guard locker{m_lock};
+ auto pool_it = m_pools.find(pool_id);
+ if (pool_it == m_pools.end()) {
+ return;
+ }
+ pool_it->second.ns_attributes[namespace_name];
+
+ // don't schedule update status as the namespace attributes are empty yet
+}
+
+template <typename I>
+void ServiceDaemon<I>::remove_namespace(int64_t pool_id,
+ const std::string& namespace_name) {
+ dout(20) << "pool_id=" << pool_id << ", namespace=" << namespace_name
+ << dendl;
+ {
+ std::lock_guard locker{m_lock};
+ auto pool_it = m_pools.find(pool_id);
+ if (pool_it == m_pools.end()) {
+ return;
+ }
+ pool_it->second.ns_attributes.erase(namespace_name);
+ }
+ schedule_update_status();
+}
+
template <typename I>
uint64_t ServiceDaemon<I>::add_or_update_callout(int64_t pool_id,
uint64_t callout_id,
schedule_update_status();
}
+template <typename I>
+void ServiceDaemon<I>::add_or_update_namespace_attribute(
+ int64_t pool_id, const std::string& namespace_name, const std::string& key,
+ const AttributeValue& value) {
+ if (namespace_name.empty()) {
+ add_or_update_attribute(pool_id, key, value);
+ return;
+ }
+
+ dout(20) << "pool_id=" << pool_id << ", "
+ << "namespace=" << namespace_name << ", "
+ << "key=" << key << ", "
+ << "value=" << value << dendl;
+
+ {
+ std::lock_guard locker{m_lock};
+ auto pool_it = m_pools.find(pool_id);
+ if (pool_it == m_pools.end()) {
+ return;
+ }
+
+ auto ns_it = pool_it->second.ns_attributes.find(namespace_name);
+ if (ns_it == pool_it->second.ns_attributes.end()) {
+ return;
+ }
+
+ ns_it->second[key] = value;
+ }
+
+ schedule_update_status();
+}
+
template <typename I>
void ServiceDaemon<I>::remove_attribute(int64_t pool_id,
const std::string& key) {
AttributeDumpVisitor attribute_dump_visitor(&f, attribute.first);
boost::apply_visitor(attribute_dump_visitor, attribute.second);
}
+
+ if (!pool_pair.second.ns_attributes.empty()) {
+ f.open_object_section("namespaces");
+ for (auto& [ns, attributes] : pool_pair.second.ns_attributes) {
+ f.open_object_section(ns.c_str());
+ for (auto& [key, value] : attributes) {
+ AttributeDumpVisitor attribute_dump_visitor(&f, key);
+ boost::apply_visitor(attribute_dump_visitor, value);
+ }
+ f.close_section(); // namespace
+ }
+ f.close_section(); // namespaces
+ }
f.close_section(); // pool
}
f.close_section(); // pools
void add_pool(int64_t pool_id, const std::string& pool_name);
void remove_pool(int64_t pool_id);
+ void add_namespace(int64_t pool_id, const std::string& namespace_name);
+ void remove_namespace(int64_t pool_id, const std::string& namespace_name);
+
uint64_t add_or_update_callout(int64_t pool_id, uint64_t callout_id,
service_daemon::CalloutLevel callout_level,
const std::string& text);
void add_or_update_attribute(int64_t pool_id, const std::string& key,
const service_daemon::AttributeValue& value);
+ void add_or_update_namespace_attribute(
+ int64_t pool_id, const std::string& namespace_name,
+ const std::string& key, const service_daemon::AttributeValue& value);
void remove_attribute(int64_t pool_id, const std::string& key);
private:
};
typedef std::map<uint64_t, Callout> Callouts;
typedef std::map<std::string, service_daemon::AttributeValue> Attributes;
+ typedef std::map<std::string, Attributes> NamespaceAttributes;
struct Pool {
std::string name;
Callouts callouts;
Attributes attributes;
+ NamespaceAttributes ns_attributes;
Pool(const std::string& name) : name(name) {
}