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.

Reply via email to