Flags() { add(&Flags::ip, "ip", "IP address to listen on. This cannot be used in conjunction\n" "with `--ip_discovery_command`."); add(&Flags::port, "port", "Port to listen on.", SlaveInfo().port()); add(&Flags::advertise_ip, "advertise_ip", "IP address advertised to reach this Mesos slave.\n" "The slave does not bind to this IP address.\n" "However, this IP address may be used to access this slave."); add(&Flags::advertise_port, "advertise_port", "Port advertised to reach this Mesos slave (along with\n" "`advertise_ip`). The slave does not bind to this port.\n" "However, this port (along with `advertise_ip`) may be used to\n" "access this slave."); add(&Flags::master, "master", "May be one of:\n" " `host:port`\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)"); add(&Flags::ip_discovery_command, "ip_discovery_command", "Optional IP discovery binary: if set, it is expected to emit\n" "the IP address which the slave will try to bind to.\n" "Cannot be used in conjunction with `--ip`."); }
int main(int argc, char** argv) { // The order of initialization is as follows: // * Windows socket stack. // * Validate flags. // * Log build information. // * Libprocess // * Logging // * Version process // * Firewall rules: should be initialized before initializing HTTP endpoints. // * Modules: Load module libraries and manifests before they // can be instantiated. // * Anonymous modules: Later components such as Allocators, and master // contender/detector might depend upon anonymous modules. // * Hooks. // * Systemd support (if it exists). // * Fetcher and Containerizer. // * Master detector. // * Authorizer. // * Garbage collector. // * Status update manager. // * Resource estimator. // * QoS controller. // * `Agent` process. // // TODO(avinash): Add more comments discussing the rationale behind for this // particular component ordering. #ifdef __WINDOWS__ // Initialize the Windows socket stack. process::Winsock winsock; #endif GOOGLE_PROTOBUF_VERIFY_VERSION; slave::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. This cannot be used in conjunction\n" "with `--ip_discovery_command`."); uint16_t port; flags.add(&port, "port", "Port to listen on.", SlaveInfo().port()); Option<string> advertise_ip; flags.add(&advertise_ip, "advertise_ip", "IP address advertised to reach this Mesos agent.\n" "The agent does not bind to this IP address.\n" "However, this IP address may be used to access this agent."); Option<string> advertise_port; flags.add(&advertise_port, "advertise_port", "Port advertised to reach this Mesos agent (along with\n" "`advertise_ip`). The agent does not bind to this port.\n" "However, this port (along with `advertise_ip`) may be used to\n" "access this agent."); Option<string> master; flags.add(&master, "master", "May be one of:\n" " `host:port`\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 slave's 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 the agent will try to bind to.\n" "Cannot be used in conjunction with `--ip`."); Try<flags::Warnings> load = flags.load("MESOS_", argc, argv); // TODO(marco): this pattern too should be abstracted away // in FlagsBase; I have seen it at least 15 times. if (load.isError()) { cerr << flags.usage(load.error()) << endl; return EXIT_FAILURE; } if (flags.help) { cout << flags.usage() << endl; return EXIT_SUCCESS; } if (flags.version) { cout << "mesos" << " " << MESOS_VERSION << endl; return EXIT_SUCCESS; } if (master.isNone() && flags.master_detector.isNone()) { cerr << flags.usage("Missing required option `--master` or " "`--master_detector`.") << endl; return EXIT_FAILURE; } if (master.isSome() && flags.master_detector.isSome()) { cerr << flags.usage("Only one of --master or --master_detector options " "should be specified."); return EXIT_FAILURE; } // Initialize libprocess. 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()); } // Log build information. 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(); } const string id = process::ID::generate("slave"); // Process ID. // If `process::initialize()` returns `false`, then it was called before this // invocation, meaning the authentication realm for libprocess-level HTTP // endpoints was set incorrectly. This should be the first invocation. if (!process::initialize(id, DEFAULT_HTTP_AUTHENTICATION_REALM)) { EXIT(EXIT_FAILURE) << "The call to `process::initialize()` in the agent's " << "`main()` was not the function's first invocation"; } logging::initialize(argv[0], flags, true); // Catch signals. // Log any flag warnings (after logging is initialized). foreach (const flags::Warning& warning, load->warnings) { LOG(WARNING) << warning.message; } spawn(new VersionProcess(), true); 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)); }
int main(int argc, char** argv) { GOOGLE_PROTOBUF_VERIFY_VERSION; slave::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", SlaveInfo().port()); string isolation; flags.add(&isolation, "isolation", "Isolation mechanism, may be one of: process, cgroups", "process"); Option<string> master; flags.add(&master, "master", "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)"); bool help; flags.add(&help, "help", "Prints this help message", false); Try<Nothing> load = flags.load("MESOS_", argc, argv); if (load.isError()) { cerr << load.error() << endl; usage(argv[0], flags); exit(1); } if (help) { usage(argv[0], flags); exit(1); } if (master.isNone()) { cerr << "Missing required option --master" << endl; exit(1); } // Initialize libprocess. if (ip.isSome()) { os::setenv("LIBPROCESS_IP", ip.get()); } os::setenv("LIBPROCESS_PORT", stringify(port)); process::initialize(); logging::initialize(argv[0], flags, true); // Catch signals. LOG(INFO) << "Creating \"" << isolation << "\" isolator"; Isolator* isolator = Isolator::create(isolation); if (isolator == NULL) { cerr << "Unrecognized isolation type: " << isolation << endl; exit(1); } LOG(INFO) << "Build: " << build::DATE << " by " << build::USER; LOG(INFO) << "Starting Mesos slave"; Try<MasterDetector*> detector = MasterDetector::create(master.get()); CHECK_SOME(detector) << "Failed to create a master detector"; Files files; Slave* slave = new Slave(flags, false, detector.get(), isolator, &files); process::spawn(slave); process::wait(slave->self()); delete slave; delete detector.get(); Isolator::destroy(isolator); return 0; }
int main(int argc, char** argv) { GOOGLE_PROTOBUF_VERIFY_VERSION; slave::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", SlaveInfo().port()); Option<string> master; flags.add(&master, "master", "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)"); bool help; flags.add(&help, "help", "Prints this help message", false); Try<Nothing> load = flags.load("MESOS_", argc, argv); if (load.isError()) { cerr << load.error() << endl; usage(argv[0], flags); EXIT(1); } if (help) { usage(argv[0], flags); EXIT(1); } if (flags.version) { version(); exit(0); } if (master.isNone()) { EXIT(1) << "Missing required option --master"; } // 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(1) << "Error loading modules: " << result.error(); } } // Initialize libprocess. if (ip.isSome()) { os::setenv("LIBPROCESS_IP", ip.get()); } os::setenv("LIBPROCESS_PORT", stringify(port)); process::initialize("slave(1)"); 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(); } Try<Containerizer*> containerizer = Containerizer::create(flags, false); if (containerizer.isError()) { EXIT(1) << "Failed to create a containerizer: " << containerizer.error(); } Try<MasterDetector*> detector = MasterDetector::create(master.get()); if (detector.isError()) { EXIT(1) << "Failed to create a master detector: " << detector.error(); } LOG(INFO) << "Starting Mesos slave"; Files files; GarbageCollector gc; StatusUpdateManager statusUpdateManager(flags); Slave* slave = new Slave( flags, detector.get(), containerizer.get(), &files, &gc, &statusUpdateManager); process::spawn(slave); process::wait(slave->self()); delete slave; delete detector.get(); delete containerizer.get(); return 0; }
int main(int argc, char** argv) { GOOGLE_PROTOBUF_VERIFY_VERSION; slave::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", SlaveInfo().port()); Option<string> master; flags.add(&master, "master", "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); // TODO(marco): this pattern too should be abstracted away // in FlagsBase; I have seen it at least 15 times. if (load.isError()) { cerr << flags.usage(load.error()) << endl; return EXIT_FAILURE; } if (flags.help) { cout << flags.usage() << endl; return EXIT_SUCCESS; } if (flags.version) { version(); return EXIT_SUCCESS; } if (master.isNone()) { cerr << flags.usage("Missing required option --master") << endl; return EXIT_FAILURE; } // 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("slave(1)"); 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(); } Fetcher fetcher; Try<Containerizer*> containerizer = Containerizer::create(flags, false, &fetcher); if (containerizer.isError()) { EXIT(EXIT_FAILURE) << "Failed to create a containerizer: " << containerizer.error(); } Try<MasterDetector*> detector = MasterDetector::create(master.get()); if (detector.isError()) { EXIT(EXIT_FAILURE) << "Failed to create a master detector: " << detector.error(); } 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)); }
int main(int argc, char** argv) { GOOGLE_PROTOBUF_VERIFY_VERSION; slave::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. This cannot be used in conjunction\n" "with `--ip_discovery_command`."); uint16_t port; flags.add(&port, "port", "Port to listen on.", SlaveInfo().port()); Option<string> advertise_ip; flags.add(&advertise_ip, "advertise_ip", "IP address advertised to reach this Mesos agent.\n" "The agent does not bind to this IP address.\n" "However, this IP address may be used to access this agent."); Option<string> advertise_port; flags.add(&advertise_port, "advertise_port", "Port advertised to reach this Mesos agent (along with\n" "`advertise_ip`). The agent does not bind to this port.\n" "However, this port (along with `advertise_ip`) may be used to\n" "access this agent."); Option<string> master; flags.add(&master, "master", "May be one of:\n" " `host:port`\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 slave's 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 the agent will try to bind to.\n" "Cannot be used in conjunction with `--ip`."); Try<Nothing> load = flags.load("MESOS_", argc, argv); // TODO(marco): this pattern too should be abstracted away // in FlagsBase; I have seen it at least 15 times. if (load.isError()) { cerr << flags.usage(load.error()) << endl; return EXIT_FAILURE; } if (flags.help) { cout << flags.usage() << endl; return EXIT_SUCCESS; } if (flags.version) { version(); return EXIT_SUCCESS; } if (master.isNone() && flags.master_detector.isNone()) { cerr << flags.usage("Missing required option `--master` or " "`--master_detector`.") << endl; return EXIT_FAILURE; } if (master.isSome() && flags.master_detector.isSome()) { cerr << flags.usage("Only one of --master or --master_detector options " "should be specified."); return EXIT_FAILURE; } // Initialize libprocess. 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()); } const string id = process::ID::generate("slave"); // Process ID. // If `process::initialize()` returns `false`, then it was called before this // invocation, meaning the authentication realm for libprocess-level HTTP // endpoints was set incorrectly. This should be the first invocation. if (!process::initialize(id, DEFAULT_HTTP_AUTHENTICATION_REALM)) { EXIT(EXIT_FAILURE) << "The call to `process::initialize()` in the agent's " << "`main()` was not the function's first invocation"; } logging::initialize(argv[0], flags, true); // Catch signals. // 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(); } } spawn(new VersionProcess(), true); 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(); } Fetcher fetcher; #ifdef __linux__ // Initialize systemd if it exists. if (systemd::exists() && flags.systemd_enable_support) { LOG(INFO) << "Inializing systemd state"; systemd::Flags systemdFlags; systemdFlags.enabled = flags.systemd_enable_support; systemdFlags.runtime_directory = flags.systemd_runtime_directory; systemdFlags.cgroups_hierarchy = flags.cgroups_hierarchy; Try<Nothing> initialize = systemd::initialize(systemdFlags); if (initialize.isError()) { EXIT(EXIT_FAILURE) << "Failed to initialize systemd: " + initialize.error(); } } #endif // __linux__ Try<Containerizer*> containerizer = Containerizer::create(flags, false, &fetcher); if (containerizer.isError()) { EXIT(EXIT_FAILURE) << "Failed to create a containerizer: " << containerizer.error(); } Try<MasterDetector*> detector_ = MasterDetector::create( master, flags.master_detector); if (detector_.isError()) { EXIT(EXIT_FAILURE) << "Failed to create a master detector: " << detector_.error(); } MasterDetector* detector = detector_.get(); Option<Authorizer*> authorizer_ = None(); string authorizerName = flags.authorizer; Result<Authorizer*> authorizer((None())); if (authorizerName != slave::DEFAULT_AUTHORIZER) { LOG(INFO) << "Creating '" << authorizerName << "' authorizer"; // NOTE: The contents of --acls will be ignored. authorizer = Authorizer::create(authorizerName); } else { // `authorizerName` is `DEFAULT_AUTHORIZER` at this point. if (flags.acls.isSome()) { LOG(INFO) << "Creating default '" << authorizerName << "' authorizer"; authorizer = Authorizer::create(flags.acls.get()); } } if (authorizer.isError()) { EXIT(EXIT_FAILURE) << "Could not create '" << authorizerName << "' authorizer: " << authorizer.error(); } else if (authorizer.isSome()) { authorizer_ = authorizer.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)); }