This is an automated email from the ASF dual-hosted git repository. bennoe pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mesos.git
commit f2ba621a6b6c48205f885007aa09d6c674de0e91 Author: Benno Evers <[email protected]> AuthorDate: Wed Nov 27 12:38:44 2019 +0100 Created unix domain socket on agent startup. Added agent code to check whether domain socket support is enabled, and if so to create or open the socket at MESOS_DOMAIN_SOCKET_LOCATION. Review: https://reviews.apache.org/r/71833 --- src/Makefile.am | 1 + src/common/domain_sockets.hpp | 93 +++++++++++++++++++++++++++++++++++++++++++ src/local/local.cpp | 1 + src/slave/main.cpp | 29 +++++++++++++- src/slave/slave.cpp | 2 + src/slave/slave.hpp | 3 ++ src/tests/cluster.cpp | 22 ++++++++++ src/tests/mock_slave.cpp | 1 + 8 files changed, 150 insertions(+), 2 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 47ad1bd..45c107c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1067,6 +1067,7 @@ libmesos_no_3rdparty_la_SOURCES += \ common/build.hpp \ common/command_utils.cpp \ common/command_utils.hpp \ + common/domain_sockets.hpp \ common/future_tracker.hpp \ common/heartbeater.hpp \ common/http.cpp \ diff --git a/src/common/domain_sockets.hpp b/src/common/domain_sockets.hpp new file mode 100644 index 0000000..6d2b0ab --- /dev/null +++ b/src/common/domain_sockets.hpp @@ -0,0 +1,93 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef __COMMON_DOMAIN_SOCKETS_HPP__ +#define __COMMON_DOMAIN_SOCKETS_HPP__ + +#include <unistd.h> // unlink() + +#include <process/socket.hpp> + +#include <stout/nothing.hpp> +#include <stout/option.hpp> +#include <stout/os/open.hpp> +#include <stout/posix/os.hpp> // chmod() +#include <stout/try.hpp> + + +namespace mesos { +namespace internal { +namespace common { + +constexpr size_t DOMAIN_SOCKET_MAX_PATH_LENGTH = 108; +constexpr int DOMAIN_SOCKET_DEFAULT_MODE = 0600; + + +inline Try<process::network::unix::Socket> createDomainSocket( + const std::string& path, + int mode = DOMAIN_SOCKET_DEFAULT_MODE) +{ + // If the file exists, and it already is a socket, we assume that it is + // left over from a previous run and unlink it before creating a new socket. + // + // Note that existing connections using this socket will not be interrupted + // by deleting the socket file. + // + // Note also that if the file exists and is not a socket, we return an Error + // when we try to `bind()`. + if (os::stat::issocket(path)) { + // TODO(bevers): Move to `os::unlink()`. + LOG(INFO) << "Removing existing socket at " << path; + ::unlink(path.c_str()); + } + + Try<process::network::unix::Socket> socket = + process::network::unix::Socket::create(); + + if (socket.isError()) { + return Error( + "Failed to create unix domain socket: " + socket.error()); + } + + Try<process::network::unix::Address> addr = + process::network::unix::Address::create(path); + + if (addr.isError()) { + return Error( + "Failed to parse path " + path + ": " + addr.error()); + } + + Try<process::network::unix::Address> bound = socket->bind(addr.get()); + if (bound.isError()) { + return Error( + "Failed to bind domain socket to path " + path + ": " + + bound.error()); + } + + Try<Nothing> chmod = os::chmod(path, mode); + if (chmod.isError()) { + return Error("Couldn't change domain socket permissions: " + + chmod.error()); + } + + return socket; +} + +} // namespace common { +} // namespace internal { +} // namespace mesos { + +#endif // __COMMON_DOMAIN_SOCKETS_HPP__ diff --git a/src/local/local.cpp b/src/local/local.cpp index 8ff4361..6a7709d 100644 --- a/src/local/local.cpp +++ b/src/local/local.cpp @@ -535,6 +535,7 @@ PID<Master> launch(const Flags& flags, Allocator* _allocator) secretGenerators->back(), nullptr, nullptr, + None(), authorizer_); // Same authorizer as master. slaves[containerizer.get()] = slave; diff --git a/src/slave/main.cpp b/src/slave/main.cpp index 1d47fba..7bce6d2 100644 --- a/src/slave/main.cpp +++ b/src/slave/main.cpp @@ -58,6 +58,7 @@ #include "common/authorization.hpp" #include "common/build.hpp" +#include "common/domain_sockets.hpp" #include "common/http.hpp" #include "hook/manager.hpp" @@ -74,6 +75,7 @@ #include "module/manager.hpp" +#include "slave/constants.hpp" #include "slave/gc.hpp" #include "slave/slave.hpp" #include "slave/task_status_update_manager.hpp" @@ -106,6 +108,8 @@ using process::Owned; using process::firewall::DisabledEndpointsFirewallRule; using process::firewall::FirewallRule; +using process::network::unix::Socket; + using std::cerr; using std::cout; using std::endl; @@ -346,11 +350,12 @@ int main(int argc, char** argv) if (flags.http_executor_domain_sockets) { if (flags.domain_socket_location.isNone()) { - flags.domain_socket_location = flags.runtime_dir + "/agent.sock"; + flags.domain_socket_location = + flags.runtime_dir + "/" + AGENT_EXECUTORS_SOCKET_FILENAME; } if (flags.domain_socket_location->size() >= - common::DOMAIN_SOCKET_MAX_LENGTH) { + common::DOMAIN_SOCKET_MAX_PATH_LENGTH) { EXIT(EXIT_FAILURE) << "Domain socket location '" << *flags.domain_socket_location << "'" << " must have less than 108 characters."; @@ -620,6 +625,25 @@ int main(int argc, char** argv) } #endif // USE_SSL_SOCKET + // Create executor domain socket if the user so desires. + Option<Socket> executorSocket = None(); + if (flags.http_executor_domain_sockets) { + // If `http_executor_domain_sockets` is true, then the location should have + // been set by the user or automatically during startup. + CHECK_SOME(flags.domain_socket_location); + + LOG(INFO) << "Creating domain socket at " << *flags.domain_socket_location; + Try<Socket> socket = + common::createDomainSocket(*flags.domain_socket_location); + + if (socket.isError()) { + EXIT(EXIT_FAILURE) + << "Failed to create domain socket: " << socket.error(); + } + + executorSocket = socket.get(); + } + Slave* slave = new Slave( id, flags, @@ -633,6 +657,7 @@ int main(int argc, char** argv) secretGenerator, volumeGidManager, futureTracker.get(), + executorSocket, authorizer_); process::spawn(slave); diff --git a/src/slave/slave.cpp b/src/slave/slave.cpp index 3f6b4fb..2607b0b 100644 --- a/src/slave/slave.cpp +++ b/src/slave/slave.cpp @@ -199,6 +199,7 @@ Slave::Slave(const string& id, SecretGenerator* _secretGenerator, VolumeGidManager* _volumeGidManager, PendingFutureTracker* _futureTracker, + const Option<process::network::unix::Socket>& _executorSocket, const Option<Authorizer*>& _authorizer) : ProcessBase(id), state(RECOVERING), @@ -230,6 +231,7 @@ Slave::Slave(const string& id, secretGenerator(_secretGenerator), volumeGidManager(_volumeGidManager), futureTracker(_futureTracker), + executorSocket(_executorSocket), authorizer(_authorizer), resourceVersion(protobuf::createUUID()) {} diff --git a/src/slave/slave.hpp b/src/slave/slave.hpp index 77b5bc0..0f3f502 100644 --- a/src/slave/slave.hpp +++ b/src/slave/slave.hpp @@ -130,6 +130,7 @@ public: mesos::SecretGenerator* secretGenerator, VolumeGidManager* volumeGidManager, PendingFutureTracker* futureTracker, + const Option<process::network::unix::Socket>& executorSocket, const Option<Authorizer*>& authorizer); ~Slave() override; @@ -871,6 +872,8 @@ private: PendingFutureTracker* futureTracker; + Option<process::network::unix::Socket> executorSocket; + const Option<Authorizer*> authorizer; // The most recent estimate of the total amount of oversubscribed diff --git a/src/tests/cluster.cpp b/src/tests/cluster.cpp index f7bc882..ffb7161 100644 --- a/src/tests/cluster.cpp +++ b/src/tests/cluster.cpp @@ -71,6 +71,7 @@ #include "authorizer/local/authorizer.hpp" #include "common/authorization.hpp" +#include "common/domain_sockets.hpp" #include "common/future_tracker.hpp" #include "common/http.hpp" @@ -119,6 +120,8 @@ using mesos::master::detector::ZooKeeperMasterDetector; using mesos::slave::ContainerTermination; +using process::network::unix::Socket; + namespace mesos { namespace internal { namespace tests { @@ -607,6 +610,24 @@ Try<process::Owned<Slave>> Slave::create( slave->secretGenerator.reset(_secretGenerator); } + Option<Socket> executorSocket = None(); + if (flags.http_executor_domain_sockets) { + // If `http_executor_domain_sockets` is true, then the location should have + // been set by the user or automatically during startup. + CHECK_SOME(flags.domain_socket_location); + + LOG(INFO) << "Creating domain socket at " << *flags.domain_socket_location; + Try<Socket> socket = + common::createDomainSocket(*flags.domain_socket_location); + + if (socket.isError()) { + EXIT(EXIT_FAILURE) + << "Failed to create domain socket: " << socket.error(); + } + + executorSocket = socket.get(); + } + // If the task status update manager is not provided, create a default one. if (taskStatusUpdateManager.isNone()) { slave->taskStatusUpdateManager.reset( @@ -643,6 +664,7 @@ Try<process::Owned<Slave>> Slave::create( secretGenerator.getOrElse(slave->secretGenerator.get()), volumeGidManager, futureTracker.getOrElse(slave->futureTracker.get()), + executorSocket, authorizer)); } diff --git a/src/tests/mock_slave.cpp b/src/tests/mock_slave.cpp index 71be957..4940285 100644 --- a/src/tests/mock_slave.cpp +++ b/src/tests/mock_slave.cpp @@ -124,6 +124,7 @@ MockSlave::MockSlave( secretGenerator, volumeGidManager, futureTracker, + None(), authorizer) { // Set up default behaviors, calling the original methods.
