TEST(OptionTest, GetOrElse) { Option<string> something = string("Something"); Option<string> none = None(); EXPECT_EQ("Something", something.getOrElse("Else")); EXPECT_EQ("Else", none.getOrElse("Else")); }
Metrics::Metrics( const LogProcess& process, const Option<string>& prefix) : recovered( prefix.getOrElse("") + "log/recovered", defer(process, &LogProcess::_recovered)), ensemble_size( prefix.getOrElse("") + "log/ensemble_size", defer(process, &LogProcess::_ensemble_size)) { process::metrics::add(recovered); process::metrics::add(ensemble_size); }
static Variant<check::Command, check::Http, check::Tcp> checkInfoToCheck( const CheckInfo& checkInfo, const string& launcherDir, const Option<string>& scheme, bool ipv6) { // Use the `CheckInfo` struct to create the right // `check::{Command, Http, Tcp}` struct. switch (checkInfo.type()) { case CheckInfo::COMMAND: { return check::Command(checkInfo.command().command()); } case CheckInfo::HTTP: { const CheckInfo::Http& http = checkInfo.http(); return check::Http( http.port(), http.has_path() ? http.path() : "", scheme.getOrElse(check::DEFAULT_HTTP_SCHEME), ipv6); } case CheckInfo::TCP: { return check::Tcp(checkInfo.tcp().port(), launcherDir); } case CheckInfo::UNKNOWN: { // TODO(josephw): Add validation at the agent or master level. // Without validation, this is considered a mis-configuration of the // task (user error). LOG(FATAL) << "Received UNKNOWN check type"; } } UNREACHABLE(); }
Try<MasterContender*> MasterContender::create( const Option<string>& zk_, const Option<string>& masterContenderModule_, const Option<Duration>& zkSessionTimeout_) { if (masterContenderModule_.isSome()) { return modules::ModuleManager::create<MasterContender>( masterContenderModule_.get()); } if (zk_.isNone()) { return new StandaloneMasterContender(); } const string& zk = zk_.get(); if (strings::startsWith(zk, "zk://")) { Try<zookeeper::URL> url = zookeeper::URL::parse(zk); if (url.isError()) { return Error(url.error()); } if (url->path == "/") { return Error( "Expecting a (chroot) path for ZooKeeper ('/' is not supported)"); } return new ZooKeeperMasterContender( url.get(), zkSessionTimeout_.getOrElse(MASTER_CONTENDER_ZK_SESSION_TIMEOUT)); } else if (strings::startsWith(zk, "file://")) { // Load the configuration out of a file. While Mesos and related // programs always use <stout/flags> to process the command line // arguments (and therefore file://) this entrypoint is exposed by // libmesos, with frameworks currently calling it and expecting it // to do the argument parsing for them which roughly matches the // argument parsing Mesos will do. // TODO(cmaloney): Rework the libmesos exposed APIs to expose // A "flags" endpoint where the framework can pass the command // line arguments and they will be parsed by <stout/flags> and the // needed flags extracted, and then change this interface to // require final values from the flags. This means that a // framework doesn't need to know how the flags are passed to // match mesos' command line arguments if it wants, but if it // needs to inspect/manipulate arguments, it can. LOG(WARNING) << "Specifying master election mechanism / ZooKeeper URL to " "be read out of a file via 'file://' is deprecated inside " "Mesos and will be removed in a future release."; const string& path = zk.substr(7); const Try<string> read = os::read(path); if (read.isError()) { return Error("Failed to read from file at '" + path + "'"); } return create(strings::trim(read.get())); } CHECK(!strings::startsWith(zk, "file://")); return Error("Failed to parse '" + zk + "'"); }
// Returns either the file descriptor associated to the Windows handle, or // `Nothing` if the handle is invalid. static Option<int> getFileDescriptorFromHandle( const Option<HANDLE>& handle, const int flags) { int fd = ::_open_osfhandle( reinterpret_cast<intptr_t>(handle.getOrElse(INVALID_HANDLE_VALUE)), flags); return fd > 0 ? Option<int>(fd) : None(); }
int main(int argc, char** argv) { GOOGLE_PROTOBUF_VERIFY_VERSION; master::Flags flags; // The following flags are executable specific (e.g., since we only // have one instance of libprocess per execution, we only want to // advertise the IP and port option once, here). Option<string> ip; flags.add(&ip, "ip", "IP address to listen on"); uint16_t port; flags.add(&port, "port", "Port to listen on", MasterInfo().port()); Option<string> advertise_ip; flags.add(&advertise_ip, "advertise_ip", "IP address advertised to reach mesos master.\n" "Mesos master does not bind using this IP address.\n" "However, this IP address may be used to access Mesos master."); Option<string> advertise_port; flags.add(&advertise_port, "advertise_port", "Port advertised to reach mesos master (alongwith advertise_ip).\n" "Mesos master does not bind using this port.\n" "However, this port (alongwith advertise_ip) may be used to\n" "access Mesos master."); Option<string> zk; flags.add(&zk, "zk", "ZooKeeper URL (used for leader election amongst masters)\n" "May be one of:\n" " zk://host1:port1,host2:port2,.../path\n" " zk://username:password@host1:port1,host2:port2,.../path\n" " file:///path/to/file (where file contains one of the above)"); // Optional IP discover script that will set the Master IP. // If set, its output is expected to be a valid parseable IP string. Option<string> ip_discovery_command; flags.add(&ip_discovery_command, "ip_discovery_command", "Optional IP discovery binary: if set, it is expected to emit\n" "the IP address which Master will try to bind to.\n" "Cannot be used in conjunction with --ip."); Try<Nothing> load = flags.load("MESOS_", argc, argv); if (load.isError()) { cerr << flags.usage(load.error()) << endl; return EXIT_FAILURE; } if (flags.version) { version(); return EXIT_SUCCESS; } if (flags.help) { cout << flags.usage() << endl; return EXIT_SUCCESS; } // Initialize modules. Note that since other subsystems may depend // upon modules, we should initialize modules before anything else. if (flags.modules.isSome()) { Try<Nothing> result = ModuleManager::load(flags.modules.get()); if (result.isError()) { EXIT(EXIT_FAILURE) << "Error loading modules: " << result.error(); } } // Initialize hooks. if (flags.hooks.isSome()) { Try<Nothing> result = HookManager::initialize(flags.hooks.get()); if (result.isError()) { EXIT(EXIT_FAILURE) << "Error installing hooks: " << result.error(); } } if (ip_discovery_command.isSome() && ip.isSome()) { EXIT(EXIT_FAILURE) << flags.usage( "Only one of --ip or --ip_discovery_command should be specified"); } if (ip_discovery_command.isSome()) { Try<string> ipAddress = os::shell(ip_discovery_command.get()); if (ipAddress.isError()) { EXIT(EXIT_FAILURE) << ipAddress.error(); } os::setenv("LIBPROCESS_IP", strings::trim(ipAddress.get())); } else if (ip.isSome()) { os::setenv("LIBPROCESS_IP", ip.get()); } os::setenv("LIBPROCESS_PORT", stringify(port)); if (advertise_ip.isSome()) { os::setenv("LIBPROCESS_ADVERTISE_IP", advertise_ip.get()); } if (advertise_port.isSome()) { os::setenv("LIBPROCESS_ADVERTISE_PORT", advertise_port.get()); } // Initialize libprocess. process::initialize("master"); logging::initialize(argv[0], flags, true); // Catch signals. LOG(INFO) << "Build: " << build::DATE << " by " << build::USER; LOG(INFO) << "Version: " << MESOS_VERSION; if (build::GIT_TAG.isSome()) { LOG(INFO) << "Git tag: " << build::GIT_TAG.get(); } if (build::GIT_SHA.isSome()) { LOG(INFO) << "Git SHA: " << build::GIT_SHA.get(); } // Create an instance of allocator. const std::string allocatorName = flags.allocator; Try<Allocator*> allocator = Allocator::create(allocatorName); if (allocator.isError()) { EXIT(EXIT_FAILURE) << "Failed to create '" << allocatorName << "' allocator: " << allocator.error(); } CHECK_NOTNULL(allocator.get()); LOG(INFO) << "Using '" << allocatorName << "' allocator"; state::Storage* storage = NULL; Log* log = NULL; if (flags.registry == "in_memory") { if (flags.registry_strict) { EXIT(EXIT_FAILURE) << "Cannot use '--registry_strict' when using in-memory storage" << " based registry"; } storage = new state::InMemoryStorage(); } else if (flags.registry == "replicated_log" || flags.registry == "log_storage") { // TODO(bmahler): "log_storage" is present for backwards // compatibility, can be removed before 0.19.0. if (flags.work_dir.isNone()) { EXIT(EXIT_FAILURE) << "--work_dir needed for replicated log based registry"; } Try<Nothing> mkdir = os::mkdir(flags.work_dir.get()); if (mkdir.isError()) { EXIT(EXIT_FAILURE) << "Failed to create work directory '" << flags.work_dir.get() << "': " << mkdir.error(); } if (zk.isSome()) { // Use replicated log with ZooKeeper. if (flags.quorum.isNone()) { EXIT(EXIT_FAILURE) << "Need to specify --quorum for replicated log based" << " registry when using ZooKeeper"; } Try<zookeeper::URL> url = zookeeper::URL::parse(zk.get()); if (url.isError()) { EXIT(EXIT_FAILURE) << "Error parsing ZooKeeper URL: " << url.error(); } log = new Log( flags.quorum.get(), path::join(flags.work_dir.get(), "replicated_log"), url.get().servers, flags.zk_session_timeout, path::join(url.get().path, "log_replicas"), url.get().authentication, flags.log_auto_initialize); } else { // Use replicated log without ZooKeeper. log = new Log( 1, path::join(flags.work_dir.get(), "replicated_log"), set<UPID>(), flags.log_auto_initialize); } storage = new state::LogStorage(log); } else { EXIT(EXIT_FAILURE) << "'" << flags.registry << "' is not a supported" << " option for registry persistence"; } CHECK_NOTNULL(storage); state::protobuf::State* state = new state::protobuf::State(storage); Registrar* registrar = new Registrar(flags, state); Repairer* repairer = new Repairer(); Files files; MasterContender* contender; MasterDetector* detector; // TODO(vinod): 'MasterContender::create()' should take // Option<string>. Try<MasterContender*> contender_ = MasterContender::create(zk.getOrElse("")); if (contender_.isError()) { EXIT(EXIT_FAILURE) << "Failed to create a master contender: " << contender_.error(); } contender = contender_.get(); // TODO(vinod): 'MasterDetector::create()' should take // Option<string>. Try<MasterDetector*> detector_ = MasterDetector::create(zk.getOrElse("")); if (detector_.isError()) { EXIT(EXIT_FAILURE) << "Failed to create a master detector: " << detector_.error(); } detector = detector_.get(); Option<Authorizer*> authorizer = None(); auto authorizerNames = strings::split(flags.authorizers, ","); if (authorizerNames.empty()) { EXIT(EXIT_FAILURE) << "No authorizer specified"; } if (authorizerNames.size() > 1) { EXIT(EXIT_FAILURE) << "Multiple authorizers not supported"; } std::string authorizerName = authorizerNames[0]; // NOTE: The flag --authorizers overrides the flag --acls, i.e. if // a non default authorizer is requested, it will be used and // the contents of --acls will be ignored. // TODO(arojas): Add support for multiple authorizers. if (authorizerName != master::DEFAULT_AUTHORIZER || flags.acls.isSome()) { Try<Authorizer*> create = Authorizer::create(authorizerName); if (create.isError()) { EXIT(EXIT_FAILURE) << "Could not create '" << authorizerName << "' authorizer: " << create.error(); } authorizer = create.get(); LOG(INFO) << "Using '" << authorizerName << "' authorizer"; if (authorizerName == master::DEFAULT_AUTHORIZER) { Try<Nothing> initialize = authorizer.get()->initialize(flags.acls.get()); if (initialize.isError()) { // Failing to initialize the authorizer leads to undefined // behavior, therefore we default to skip authorization // altogether. LOG(WARNING) << "Authorization disabled: Failed to initialize '" << authorizerName << "' authorizer: " << initialize.error(); delete authorizer.get(); authorizer = None(); } } else if (flags.acls.isSome()) { LOG(WARNING) << "Ignoring contents of --acls flag, because '" << authorizerName << "' authorizer will be used instead " << " of the default."; } } Option<shared_ptr<RateLimiter>> slaveRemovalLimiter = None(); if (flags.slave_removal_rate_limit.isSome()) { // Parse the flag value. // TODO(vinod): Move this parsing logic to flags once we have a // 'Rate' abstraction in stout. vector<string> tokens = strings::tokenize(flags.slave_removal_rate_limit.get(), "/"); if (tokens.size() != 2) { EXIT(EXIT_FAILURE) << "Invalid slave_removal_rate_limit: " << flags.slave_removal_rate_limit.get() << ". Format is <Number of slaves>/<Duration>"; } Try<int> permits = numify<int>(tokens[0]); if (permits.isError()) { EXIT(EXIT_FAILURE) << "Invalid slave_removal_rate_limit: " << flags.slave_removal_rate_limit.get() << ". Format is <Number of slaves>/<Duration>" << ": " << permits.error(); } Try<Duration> duration = Duration::parse(tokens[1]); if (duration.isError()) { EXIT(EXIT_FAILURE) << "Invalid slave_removal_rate_limit: " << flags.slave_removal_rate_limit.get() << ". Format is <Number of slaves>/<Duration>" << ": " << duration.error(); } slaveRemovalLimiter = new RateLimiter(permits.get(), duration.get()); } if (flags.firewall_rules.isSome()) { vector<Owned<FirewallRule>> rules; const Firewall firewall = flags.firewall_rules.get(); if (firewall.has_disabled_endpoints()) { hashset<string> paths; foreach (const string& path, firewall.disabled_endpoints().paths()) { paths.insert(path); } rules.emplace_back(new DisabledEndpointsFirewallRule(paths)); }
// Try to extract sourcePath into directory. If sourcePath is // recognized as an archive it will be extracted and true returned; // if not recognized then false will be returned. An Error is // returned if the extraction command fails. static Try<bool> extract( const string& sourcePath, const string& destinationDirectory) { Try<Nothing> result = Nothing(); Option<Subprocess::IO> in = None(); Option<Subprocess::IO> out = None(); vector<string> command; // Extract any .tar, .tgz, tar.gz, tar.bz2 or zip files. if (strings::endsWith(sourcePath, ".tar") || strings::endsWith(sourcePath, ".tgz") || strings::endsWith(sourcePath, ".tar.gz") || strings::endsWith(sourcePath, ".tbz2") || strings::endsWith(sourcePath, ".tar.bz2") || strings::endsWith(sourcePath, ".txz") || strings::endsWith(sourcePath, ".tar.xz")) { command = {"tar", "-C", destinationDirectory, "-xf", sourcePath}; } else if (strings::endsWith(sourcePath, ".gz")) { string pathWithoutExtension = sourcePath.substr(0, sourcePath.length() - 3); string filename = Path(pathWithoutExtension).basename(); string destinationPath = path::join(destinationDirectory, filename); command = {"gunzip", "-d", "-c"}; in = Subprocess::PATH(sourcePath); out = Subprocess::PATH(destinationPath); } else if (strings::endsWith(sourcePath, ".zip")) { #ifdef __WINDOWS__ command = {"powershell", "-NoProfile", "-Command", "Expand-Archive", "-Force", "-Path", sourcePath, "-DestinationPath", destinationDirectory}; #else command = {"unzip", "-o", "-d", destinationDirectory, sourcePath}; #endif // __WINDOWS__ } else { return false; } CHECK_GT(command.size(), 0u); Try<Subprocess> extractProcess = subprocess( command[0], command, in.getOrElse(Subprocess::PATH(os::DEV_NULL)), out.getOrElse(Subprocess::FD(STDOUT_FILENO)), Subprocess::FD(STDERR_FILENO)); if (extractProcess.isError()) { return Error( "Failed to extract '" + sourcePath + "': '" + strings::join(" ", command) + "' failed: " + extractProcess.error()); } // `status()` never fails or gets discarded. int status = extractProcess->status()->get(); if (!WSUCCEEDED(status)) { return Error( "Failed to extract '" + sourcePath + "': '" + strings::join(" ", command) + "' failed: " + WSTRINGIFY(status)); } LOG(INFO) << "Extracted '" << sourcePath << "' into '" << destinationDirectory << "'"; return true; }
Future<size_t> RegistryClientProcess::getBlob( const string& path, const Option<string>& digest, const Path& filePath) { const string dirName = filePath.dirname(); Try<Nothing> mkdir = os::mkdir(dirName, true); if (mkdir.isError()) { return Failure( "Failed to create directory to download blob: " + mkdir.error()); } if (strings::contains(path, " ")) { return Failure("Invalid repository path: " + path); } const string blobURLPath = "v2/" + path + "/blobs/" + digest.getOrElse(""); http::URL blobURL(registryServer_); blobURL.path = blobURLPath; return doHttpGet(blobURL, None(), true, true, None()) .then([this, blobURLPath, digest, filePath]( const http::Response& response) -> Future<size_t> { Try<int> fd = os::open( filePath.value, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if (fd.isError()) { return Failure("Failed to open file '" + filePath.value + "': " + fd.error()); } Try<Nothing> nonblock = os::nonblock(fd.get()); if (nonblock.isError()) { Try<Nothing> close = os::close(fd.get()); if (close.isError()) { LOG(WARNING) << "Failed to close the file descriptor for file '" << stringify(filePath) << "': " << close.error(); } return Failure( "Failed to set non-blocking mode for file: " + filePath.value); } // TODO(jojy): Add blob validation. // TODO(jojy): Add check for max size. Option<Pipe::Reader> reader = response.reader; if (reader.isNone()) { Try<Nothing> close = os::close(fd.get()); if (close.isError()) { LOG(WARNING) << "Failed to close the file descriptor for file '" << stringify(filePath) << "': " << close.error(); } return Failure("Failed to get streaming reader from blob response"); } return saveBlob(fd.get(), reader.get()) .onAny([blobURLPath, digest, filePath, fd]( const Future<size_t>& future) { Try<Nothing> close = os::close(fd.get()); if (close.isError()) { LOG(WARNING) << "Failed to close the file descriptor for blob '" << stringify(filePath) << "': " << close.error(); } if (future.isFailed()) { LOG(WARNING) << "Failed to save blob requested from '" << blobURLPath << "' to path '" << stringify(filePath) << "': " << future.failure(); } if (future.isDiscarded()) { LOG(WARNING) << "Failed to save blob requested from '" << blobURLPath << "' to path '" << stringify(filePath) << "': future discarded"; } }); }); }
Future<Nothing> NvidiaGpuIsolatorProcess::update( const ContainerID& containerId, const Resources& resources) { if (containerId.has_parent()) { return Failure("Not supported for nested containers"); } if (!infos.contains(containerId)) { return Failure("Unknown container"); } Info* info = CHECK_NOTNULL(infos[containerId]); Option<double> gpus = resources.gpus(); // Make sure that the `gpus` resource is not fractional. // We rely on scalar resources only having 3 digits of precision. if (static_cast<long long>(gpus.getOrElse(0.0) * 1000.0) % 1000 != 0) { return Failure("The 'gpus' resource must be an unsigned integer"); } size_t requested = static_cast<size_t>(resources.gpus().getOrElse(0.0)); // Update the GPU allocation to reflect the new total. if (requested > info->allocated.size()) { size_t additional = requested - info->allocated.size(); return allocator.allocate(additional) .then(defer(PID<NvidiaGpuIsolatorProcess>(this), &NvidiaGpuIsolatorProcess::_update, containerId, lambda::_1)); } else if (requested < info->allocated.size()) { size_t fewer = info->allocated.size() - requested; set<Gpu> deallocated; for (size_t i = 0; i < fewer; i++) { const auto gpu = info->allocated.begin(); cgroups::devices::Entry entry; entry.selector.type = Entry::Selector::Type::CHARACTER; entry.selector.major = gpu->major; entry.selector.minor = gpu->minor; entry.access.read = true; entry.access.write = true; entry.access.mknod = true; Try<Nothing> deny = cgroups::devices::deny( hierarchy, info->cgroup, entry); if (deny.isError()) { return Failure("Failed to deny cgroups access to GPU device" " '" + stringify(entry) + "': " + deny.error()); } deallocated.insert(*gpu); info->allocated.erase(gpu); } return allocator.deallocate(deallocated); } return Nothing(); }
int main(int argc, char** argv) { GOOGLE_PROTOBUF_VERIFY_VERSION; master::Flags flags; // The following flags are executable specific (e.g., since we only // have one instance of libprocess per execution, we only want to // advertise the IP and port option once, here). Option<string> ip; flags.add(&ip, "ip", "IP address to listen on"); uint16_t port; flags.add(&port, "port", "Port to listen on", MasterInfo().port()); Option<string> zk; flags.add(&zk, "zk", "ZooKeeper URL (used for leader election amongst masters)\n" "May be one of:\n" " zk://host1:port1,host2:port2,.../path\n" " zk://username:password@host1:port1,host2:port2,.../path\n" " file:///path/to/file (where file contains one of the above)"); Try<Nothing> load = flags.load("MESOS_", argc, argv); if (load.isError()) { cerr << flags.usage(load.error()) << endl; return EXIT_FAILURE; } if (flags.version) { version(); return EXIT_SUCCESS; } if (flags.help) { cout << flags.usage() << endl; return EXIT_SUCCESS; } // Initialize modules. Note that since other subsystems may depend // upon modules, we should initialize modules before anything else. if (flags.modules.isSome()) { Try<Nothing> result = ModuleManager::load(flags.modules.get()); if (result.isError()) { EXIT(EXIT_FAILURE) << "Error loading modules: " << result.error(); } } // Initialize hooks. if (flags.hooks.isSome()) { Try<Nothing> result = HookManager::initialize(flags.hooks.get()); if (result.isError()) { EXIT(EXIT_FAILURE) << "Error installing hooks: " << result.error(); } } // Initialize libprocess. if (ip.isSome()) { os::setenv("LIBPROCESS_IP", ip.get()); } os::setenv("LIBPROCESS_PORT", stringify(port)); process::initialize("master"); logging::initialize(argv[0], flags, true); // Catch signals. LOG(INFO) << "Build: " << build::DATE << " by " << build::USER; LOG(INFO) << "Version: " << MESOS_VERSION; if (build::GIT_TAG.isSome()) { LOG(INFO) << "Git tag: " << build::GIT_TAG.get(); } if (build::GIT_SHA.isSome()) { LOG(INFO) << "Git SHA: " << build::GIT_SHA.get(); } // Create an instance of allocator. const std::string allocatorName = flags.allocator; Try<Allocator*> allocator = Allocator::create(allocatorName); if (allocator.isError()) { EXIT(EXIT_FAILURE) << "Failed to create '" << allocatorName << "' allocator: " << allocator.error(); } CHECK_NOTNULL(allocator.get()); LOG(INFO) << "Using '" << allocatorName << "' allocator"; state::Storage* storage = NULL; Log* log = NULL; if (flags.registry == "in_memory") { if (flags.registry_strict) { EXIT(EXIT_FAILURE) << "Cannot use '--registry_strict' when using in-memory storage" << " based registry"; } storage = new state::InMemoryStorage(); } else if (flags.registry == "replicated_log" || flags.registry == "log_storage") { // TODO(bmahler): "log_storage" is present for backwards // compatibility, can be removed before 0.19.0. if (flags.work_dir.isNone()) { EXIT(EXIT_FAILURE) << "--work_dir needed for replicated log based registry"; } Try<Nothing> mkdir = os::mkdir(flags.work_dir.get()); if (mkdir.isError()) { EXIT(EXIT_FAILURE) << "Failed to create work directory '" << flags.work_dir.get() << "': " << mkdir.error(); } if (zk.isSome()) { // Use replicated log with ZooKeeper. if (flags.quorum.isNone()) { EXIT(EXIT_FAILURE) << "Need to specify --quorum for replicated log based" << " registry when using ZooKeeper"; } Try<zookeeper::URL> url = zookeeper::URL::parse(zk.get()); if (url.isError()) { EXIT(EXIT_FAILURE) << "Error parsing ZooKeeper URL: " << url.error(); } log = new Log( flags.quorum.get(), path::join(flags.work_dir.get(), "replicated_log"), url.get().servers, flags.zk_session_timeout, path::join(url.get().path, "log_replicas"), url.get().authentication, flags.log_auto_initialize); } else { // Use replicated log without ZooKeeper. log = new Log( 1, path::join(flags.work_dir.get(), "replicated_log"), set<UPID>(), flags.log_auto_initialize); } storage = new state::LogStorage(log); } else { EXIT(EXIT_FAILURE) << "'" << flags.registry << "' is not a supported" << " option for registry persistence"; } CHECK_NOTNULL(storage); state::protobuf::State* state = new state::protobuf::State(storage); Registrar* registrar = new Registrar(flags, state); Repairer* repairer = new Repairer(); Files files; MasterContender* contender; MasterDetector* detector; // TODO(vinod): 'MasterContender::create()' should take // Option<string>. Try<MasterContender*> contender_ = MasterContender::create(zk.getOrElse("")); if (contender_.isError()) { EXIT(EXIT_FAILURE) << "Failed to create a master contender: " << contender_.error(); } contender = contender_.get(); // TODO(vinod): 'MasterDetector::create()' should take // Option<string>. Try<MasterDetector*> detector_ = MasterDetector::create(zk.getOrElse("")); if (detector_.isError()) { EXIT(EXIT_FAILURE) << "Failed to create a master detector: " << detector_.error(); } detector = detector_.get(); Option<Authorizer*> authorizer = None(); if (flags.acls.isSome()) { Try<Owned<Authorizer>> create = Authorizer::create(flags.acls.get()); if (create.isError()) { EXIT(EXIT_FAILURE) << "Failed to initialize the authorizer: " << create.error() << " (see --acls flag)"; } // Now pull out the authorizer but need to make a copy since we // get a 'const &' from 'Try::get'. authorizer = Owned<Authorizer>(create.get()).release(); } Option<shared_ptr<RateLimiter>> slaveRemovalLimiter = None(); if (flags.slave_removal_rate_limit.isSome()) { // Parse the flag value. // TODO(vinod): Move this parsing logic to flags once we have a // 'Rate' abstraction in stout. vector<string> tokens = strings::tokenize(flags.slave_removal_rate_limit.get(), "/"); if (tokens.size() != 2) { EXIT(EXIT_FAILURE) << "Invalid slave_removal_rate_limit: " << flags.slave_removal_rate_limit.get() << ". Format is <Number of slaves>/<Duration>"; } Try<int> permits = numify<int>(tokens[0]); if (permits.isError()) { EXIT(EXIT_FAILURE) << "Invalid slave_removal_rate_limit: " << flags.slave_removal_rate_limit.get() << ". Format is <Number of slaves>/<Duration>" << ": " << permits.error(); } Try<Duration> duration = Duration::parse(tokens[1]); if (duration.isError()) { EXIT(EXIT_FAILURE) << "Invalid slave_removal_rate_limit: " << flags.slave_removal_rate_limit.get() << ". Format is <Number of slaves>/<Duration>" << ": " << duration.error(); } slaveRemovalLimiter = new RateLimiter(permits.get(), duration.get()); } if (flags.firewall_rules.isSome()) { vector<Owned<FirewallRule>> rules; const Firewall firewall = flags.firewall_rules.get(); if (firewall.has_disabled_endpoints()) { hashset<string> paths; foreach (const string& path, firewall.disabled_endpoints().paths()) { paths.insert(path); } rules.emplace_back(new DisabledEndpointsFirewallRule(paths)); }