zookeeper chroot fix (#1430)

* added root and identity section to zookeeper configuration [#CLICKHOUSE-3031]

* added root and identity section to zookeeper configuration [#CLICKHOUSE-3031]

* moved root section in zookeeper configuration [#CLICKHOUSE-3031]

* fixed root section in zookeeper configuration [#CLICKHOUSE-3031]

* added tests [#CLICKHOUSE-3031]

* replaced tabs to spaces in config files [#CLICKHOUSE-3031]

* fix build [#CLICKHOUSE-3031]

* added chech that root starts with '/' in zookeeper config file [#CLICKHOUSE-3031]

* added comments [#CLICKHOUSE-3031]

* Check if zookeeper chroot exists before start. Remove tailing slash form chroot. [#CLICKHOUSE-3400]

* added starting '/' to zookeeper path in ReplicatedMergeTree
This commit is contained in:
KochetovNicolai 2017-11-02 01:59:27 +03:00 committed by alexey-milovidov
parent 9fb4e86270
commit bfb4e8f3fe
3 changed files with 23 additions and 7 deletions

View File

@ -71,7 +71,8 @@ void ZooKeeper::processCallback(zhandle_t * zh, int type, int state, const char
destroyContext(context); destroyContext(context);
} }
void ZooKeeper::init(const std::string & hosts_, const std::string & identity_, int32_t session_timeout_ms_) void ZooKeeper::init(const std::string & hosts_, const std::string & identity_,
int32_t session_timeout_ms_, bool check_root_exists)
{ {
log = &Logger::get("ZooKeeper"); log = &Logger::get("ZooKeeper");
zoo_set_debug_level(ZOO_LOG_LEVEL_ERROR); zoo_set_debug_level(ZOO_LOG_LEVEL_ERROR);
@ -87,7 +88,7 @@ void ZooKeeper::init(const std::string & hosts_, const std::string & identity_,
if (!identity.empty()) if (!identity.empty())
{ {
auto code = zoo_add_auth(impl, "digest", identity.c_str(), static_cast<int>(identity.size()), 0, 0); auto code = zoo_add_auth(impl, "digest", identity.c_str(), static_cast<int>(identity.size()), nullptr, nullptr);
if (code != ZOK) if (code != ZOK)
throw KeeperException("Zookeeper authentication failed. Hosts are " + hosts, code); throw KeeperException("Zookeeper authentication failed. Hosts are " + hosts, code);
@ -97,11 +98,15 @@ void ZooKeeper::init(const std::string & hosts_, const std::string & identity_,
default_acl = &ZOO_OPEN_ACL_UNSAFE; default_acl = &ZOO_OPEN_ACL_UNSAFE;
LOG_TRACE(log, "initialized, hosts: " << hosts); LOG_TRACE(log, "initialized, hosts: " << hosts);
if (check_root_exists && !exists("/"))
throw KeeperException("Zookeeper root doesn't exist. You should create root node before start.");
} }
ZooKeeper::ZooKeeper(const std::string & hosts, const std::string & identity, int32_t session_timeout_ms) ZooKeeper::ZooKeeper(const std::string & hosts, const std::string & identity,
int32_t session_timeout_ms, bool check_root_exists)
{ {
init(hosts, identity, session_timeout_ms); init(hosts, identity, session_timeout_ms, check_root_exists);
} }
struct ZooKeeperArgs struct ZooKeeperArgs
@ -115,6 +120,7 @@ struct ZooKeeperArgs
std::string root; std::string root;
session_timeout_ms = DEFAULT_SESSION_TIMEOUT; session_timeout_ms = DEFAULT_SESSION_TIMEOUT;
has_chroot = false;
for (const auto & key : keys) for (const auto & key : keys)
{ {
if (startsWith(key, "node")) if (startsWith(key, "node"))
@ -154,19 +160,24 @@ struct ZooKeeperArgs
{ {
if (root.front() != '/') if (root.front() != '/')
throw KeeperException(std::string("Root path in config file should start with '/', but got ") + root); throw KeeperException(std::string("Root path in config file should start with '/', but got ") + root);
if (root.back() == '/')
root.pop_back();
hosts += root; hosts += root;
has_chroot = true;
} }
} }
std::string hosts; std::string hosts;
std::string identity; std::string identity;
int session_timeout_ms; int session_timeout_ms;
bool has_chroot;
}; };
ZooKeeper::ZooKeeper(const Poco::Util::AbstractConfiguration & config, const std::string & config_name) ZooKeeper::ZooKeeper(const Poco::Util::AbstractConfiguration & config, const std::string & config_name)
{ {
ZooKeeperArgs args(config, config_name); ZooKeeperArgs args(config, config_name);
init(args.hosts, args.identity, args.session_timeout_ms); init(args.hosts, args.identity, args.session_timeout_ms, args.has_chroot);
} }
WatchCallback ZooKeeper::callbackForEvent(const EventPtr & event) WatchCallback ZooKeeper::callbackForEvent(const EventPtr & event)

View File

@ -54,7 +54,8 @@ class ZooKeeper
public: public:
using Ptr = std::shared_ptr<ZooKeeper>; using Ptr = std::shared_ptr<ZooKeeper>;
ZooKeeper(const std::string & hosts, const std::string & identity = "", int32_t session_timeout_ms = DEFAULT_SESSION_TIMEOUT); ZooKeeper(const std::string & hosts, const std::string & identity = "",
int32_t session_timeout_ms = DEFAULT_SESSION_TIMEOUT, bool check_root_exists = false);
/** Config of the form: /** Config of the form:
<zookeeper> <zookeeper>
@ -357,7 +358,8 @@ private:
friend struct WatchContext; friend struct WatchContext;
friend class EphemeralNodeHolder; friend class EphemeralNodeHolder;
void init(const std::string & hosts, const std::string & identity, int32_t session_timeout_ms); void init(const std::string & hosts, const std::string & identity,
int32_t session_timeout_ms, bool check_root_exists);
void removeChildrenRecursive(const std::string & path); void removeChildrenRecursive(const std::string & path);
void tryRemoveChildrenRecursive(const std::string & path); void tryRemoveChildrenRecursive(const std::string & path);

View File

@ -211,6 +211,9 @@ StorageReplicatedMergeTree::StorageReplicatedMergeTree(
{ {
if (!zookeeper_path.empty() && zookeeper_path.back() == '/') if (!zookeeper_path.empty() && zookeeper_path.back() == '/')
zookeeper_path.resize(zookeeper_path.size() - 1); zookeeper_path.resize(zookeeper_path.size() - 1);
/// If zookeeper chroot prefix is used, path should starts with '/', because chroot concatenates without it.
if (!zookeeper_path.empty() && zookeeper_path.front() != '/')
zookeeper_path = "/" + zookeeper_path;
replica_path = zookeeper_path + "/replicas/" + replica_name; replica_path = zookeeper_path + "/replicas/" + replica_name;
bool skip_sanity_checks = false; bool skip_sanity_checks = false;