Repository: mesos
Updated Branches:
  refs/heads/master 721ea1145 -> 69393f77d


Added Systemd environment check to LinuxLauncher.

This will be used to perform Systemd specific actions.

Review: https://reviews.apache.org/r/38634


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/ac76392b
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/ac76392b
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/ac76392b

Branch: refs/heads/master
Commit: ac76392bc64a8a570e3519e875fce91ea4064d56
Parents: 721ea11
Author: Joris Van Remoortere <[email protected]>
Authored: Tue Sep 22 10:51:39 2015 -0400
Committer: Joris Van Remoortere <[email protected]>
Committed: Wed Sep 23 20:56:39 2015 -0700

----------------------------------------------------------------------
 src/Makefile.am                            |   3 +
 src/linux/systemd.cpp                      | 100 ++++++++++++++++++++++++
 src/linux/systemd.hpp                      |  40 ++++++++++
 src/slave/containerizer/linux_launcher.cpp |  56 ++++++++-----
 src/slave/containerizer/linux_launcher.hpp |   6 +-
 5 files changed, 184 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/ac76392b/src/Makefile.am
----------------------------------------------------------------------
diff --git a/src/Makefile.am b/src/Makefile.am
index 74c1154..776483b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -682,6 +682,7 @@ if OS_LINUX
   libmesos_no_3rdparty_la_SOURCES += linux/cgroups.cpp
   libmesos_no_3rdparty_la_SOURCES += linux/fs.cpp
   libmesos_no_3rdparty_la_SOURCES += linux/perf.cpp
+  libmesos_no_3rdparty_la_SOURCES += linux/systemd.cpp
   libmesos_no_3rdparty_la_SOURCES += 
slave/containerizer/isolators/cgroups/cpushare.cpp
   libmesos_no_3rdparty_la_SOURCES += 
slave/containerizer/isolators/cgroups/mem.cpp
   libmesos_no_3rdparty_la_SOURCES += 
slave/containerizer/isolators/cgroups/perf_event.cpp
@@ -693,6 +694,7 @@ if OS_LINUX
 else
   EXTRA_DIST += linux/cgroups.cpp
   EXTRA_DIST += linux/fs.cpp
+  EXTRA_DIST += linux/systemd.cpp
 endif
 
 if WITH_NETWORK_ISOLATOR
@@ -763,6 +765,7 @@ libmesos_no_3rdparty_la_SOURCES +=                          
        \
        linux/ns.hpp                                                    \
        linux/perf.hpp                                                  \
        linux/sched.hpp                                                 \
+       linux/systemd.hpp                                               \
        local/flags.hpp                                                 \
        local/local.hpp                                                 \
        logging/flags.hpp                                               \

http://git-wip-us.apache.org/repos/asf/mesos/blob/ac76392b/src/linux/systemd.cpp
----------------------------------------------------------------------
diff --git a/src/linux/systemd.cpp b/src/linux/systemd.cpp
new file mode 100644
index 0000000..7084e70
--- /dev/null
+++ b/src/linux/systemd.cpp
@@ -0,0 +1,100 @@
+/**
+ * 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.
+ */
+
+#include "linux/systemd.hpp"
+
+#include <string>
+#include <vector>
+
+#include <stout/os.hpp>
+#include <stout/strings.hpp>
+#include <stout/try.hpp>
+
+using std::string;
+using std::vector;
+
+namespace systemd {
+
+int DELEGATE_MINIMUM_VERSION = 218;
+
+bool exists()
+{
+  // This is static as the init system should not change while we are running.
+  static const bool exists = []() -> bool {
+    // (1) Test whether `/sbin/init` links to systemd.
+    const Result<string> realpath = os::realpath("/sbin/init");
+    if (realpath.isError() || realpath.isNone()) {
+      LOG(WARNING) << "Failed to test /sbin/init for systemd environment: "
+                   << realpath.error();
+
+      return false;
+    }
+
+    CHECK_SOME(realpath);
+
+    // (2) Testing whether we have a systemd version.
+    const string command = realpath.get() + " --version";
+    Try<string> versionCommand = os::shell(command);
+
+    if (versionCommand.isError()) {
+      LOG(WARNING) << "Failed to test command '" << command << "': "
+                   << versionCommand.error();
+
+      return false;
+    }
+
+    vector<string> tokens = strings::tokenize(versionCommand.get(), " \n");
+
+    // We need at least a name and a version number to match systemd.
+    if (tokens.size() < 2) {
+      return false;
+    }
+
+    if (tokens[0] != "systemd") {
+      return false;
+    }
+
+    Try<int> version = numify<int>(tokens[1]);
+    if (version.isError()) {
+      LOG(WARNING) << "Failed to parse systemd version '" << tokens[1] << "'";
+      return false;
+    }
+
+    LOG(INFO) << "systemd version `" << version.get() << "` detected";
+
+    // We log a warning if the version is below 218. This is because the
+    // `Delegate` flag was introduced in version 218. Some systems, like RHEL 
7,
+    // have patched versions that are below 218 but still have the `Delegate`
+    // flag. This is why we warn / inform users rather than failing. See
+    // MESOS-3352.
+    if (version.get() < DELEGATE_MINIMUM_VERSION) {
+      LOG(WARNING)
+        << "Required functionality `Delegate` was introduced in Version `"
+        << DELEGATE_MINIMUM_VERSION << "`. Your system may not function"
+        << " properly; however since some distributions have patched systemd"
+        << " packages, your system may still be functional. This is why we 
keep"
+        << " running. See MESOS-3352 for more information";
+    }
+
+    return true;
+  }();
+
+  return exists;
+}
+
+} // namespace systemd {

http://git-wip-us.apache.org/repos/asf/mesos/blob/ac76392b/src/linux/systemd.hpp
----------------------------------------------------------------------
diff --git a/src/linux/systemd.hpp b/src/linux/systemd.hpp
new file mode 100644
index 0000000..81db822
--- /dev/null
+++ b/src/linux/systemd.hpp
@@ -0,0 +1,40 @@
+/**
+ * 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 __SYSTEMD_HPP__
+#define __SYSTEMD_HPP__
+
+namespace systemd {
+
+/**
+ * Check if we are on a systemd environment by:
+ * (1) Testing whether `/sbin/init` links to systemd.
+ * (2) Testing whether we have a systemd version.
+ * TODO(jmlvanre): This logic can be made more robust, but there does not seem
+ * to be a standardized way to test the executing init system in a
+ * cross-platform way. The task is made slightly easier because we are only
+ * interested in identifying if we are running on systemd, not which specific
+ * init system is running.
+ *
+ * @return Whether running on a systemd environment.
+ */
+bool exists();
+
+} // namespace systemd {
+
+#endif // __SYSTEMD_HPP__

http://git-wip-us.apache.org/repos/asf/mesos/blob/ac76392b/src/slave/containerizer/linux_launcher.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/linux_launcher.cpp 
b/src/slave/containerizer/linux_launcher.cpp
index 459af1b..55155ca 100644
--- a/src/slave/containerizer/linux_launcher.cpp
+++ b/src/slave/containerizer/linux_launcher.cpp
@@ -34,6 +34,7 @@
 
 #include "linux/cgroups.hpp"
 #include "linux/ns.hpp"
+#include "linux/systemd.hpp"
 
 #include "mesos/resources.hpp"
 
@@ -65,42 +66,56 @@ static ContainerID container(const string& cgroup)
 }
 
 
+// `_systemdHierarchy` is only set if running on a systemd environment.
 LinuxLauncher::LinuxLauncher(
     const Flags& _flags,
-    const string& _hierarchy)
+    const string& _freezerHierarchy,
+    const Option<string>& _systemdHierarchy)
   : flags(_flags),
-    hierarchy(_hierarchy) {}
+    freezerHierarchy(_freezerHierarchy),
+    systemdHierarchy(_systemdHierarchy) {}
 
 
 Try<Launcher*> LinuxLauncher::create(const Flags& flags)
 {
-  Try<string> hierarchy = cgroups::prepare(
+  Try<string> freezerHierarchy = cgroups::prepare(
       flags.cgroups_hierarchy,
       "freezer",
       flags.cgroups_root);
 
-  if (hierarchy.isError()) {
-    return Error("Failed to create Linux launcher: " + hierarchy.error());
+  if (freezerHierarchy.isError()) {
+    return Error(
+        "Failed to create Linux launcher: " + freezerHierarchy.error());
   }
 
-  // Ensure that no other subsystem is attached to the hierarchy.
-  Try<set<string>> subsystems = cgroups::subsystems(hierarchy.get());
+  // Ensure that no other subsystem is attached to the freezer hierarchy.
+  Try<set<string>> subsystems = cgroups::subsystems(freezerHierarchy.get());
   if (subsystems.isError()) {
     return Error(
         "Failed to get the list of attached subsystems for hierarchy " +
-        hierarchy.get());
+        freezerHierarchy.get());
   } else if (subsystems.get().size() != 1) {
     return Error(
         "Unexpected subsystems found attached to the hierarchy " +
-        hierarchy.get());
+        freezerHierarchy.get());
   }
 
-  LOG(INFO) << "Using " << hierarchy.get()
+  LOG(INFO) << "Using " << freezerHierarchy.get()
             << " as the freezer hierarchy for the Linux launcher";
 
+  // On systemd environments we currently migrate executor pids into a separate
+  // executor slice. This allows the life-time of the executor to be extended
+  // past the life-time of the slave. See MESOS-3352.
+  // The LinuxLauncher takes responsibility for creating and starting this
+  // slice. It then migrates executor pids into this slice before it "unpauses"
+  // the executor. This is the same pattern as the freezer.
+
   return new LinuxLauncher(
       flags,
-      hierarchy.get());
+      freezerHierarchy.get(),
+      systemd::exists() ?
+        Some(flags.cgroups_hierarchy + "/systemd") :
+        Option<std::string>::none());
 }
 
 
@@ -131,7 +146,7 @@ Future<hashset<ContainerID>> LinuxLauncher::recover(
     // destroy() when we clean up.
     pids.put(containerId, pid);
 
-    Try<bool> exists = cgroups::exists(hierarchy, cgroup(containerId));
+    Try<bool> exists = cgroups::exists(freezerHierarchy, cgroup(containerId));
 
     if (!exists.get()) {
       // This may occur if the freezer cgroup was destroyed but the
@@ -147,7 +162,9 @@ Future<hashset<ContainerID>> LinuxLauncher::recover(
   }
 
   // Return the set of orphan containers.
-  Try<vector<string>> cgroups = cgroups::get(hierarchy, flags.cgroups_root);
+  Try<vector<string>> cgroups =
+    cgroups::get(freezerHierarchy, flags.cgroups_root);
+
   if (cgroups.isError()) {
     return Failure(cgroups.error());
   }
@@ -215,14 +232,15 @@ Try<pid_t> LinuxLauncher::fork(
     const Option<int>& namespaces)
 {
   // Create a freezer cgroup for this container if necessary.
-  Try<bool> exists = cgroups::exists(hierarchy, cgroup(containerId));
+  Try<bool> exists = cgroups::exists(freezerHierarchy, cgroup(containerId));
   if (exists.isError()) {
     return Error("Failed to check existence of freezer cgroup: " +
                  exists.error());
   }
 
   if (!exists.get()) {
-    Try<Nothing> created = cgroups::create(hierarchy, cgroup(containerId));
+    Try<Nothing> created =
+      cgroups::create(freezerHierarchy, cgroup(containerId));
 
     if (created.isError()) {
       return Error("Failed to create freezer cgroup: " + created.error());
@@ -266,7 +284,7 @@ Try<pid_t> LinuxLauncher::fork(
   // TODO(jieyu): Move this logic to the subprocess (i.e.,
   // mesos-containerizer launch).
   Try<Nothing> assign = cgroups::assign(
-      hierarchy,
+      freezerHierarchy,
       cgroup(containerId),
       child.get().pid());
 
@@ -313,7 +331,7 @@ Future<Nothing> LinuxLauncher::destroy(const ContainerID& 
containerId)
 
   // Just return if the cgroup was destroyed and the slave didn't receive the
   // notification. See comment in recover().
-  Try<bool> exists = cgroups::exists(hierarchy, cgroup(containerId));
+  Try<bool> exists = cgroups::exists(freezerHierarchy, cgroup(containerId));
   if (exists.isError()) {
     return Failure("Failed to check existence of freezer cgroup: " +
                    exists.error());
@@ -334,14 +352,14 @@ Future<Nothing> LinuxLauncher::destroy(const ContainerID& 
containerId)
             (Future<Nothing>(*)(const string&,
                                 const string&,
                                 const Duration&))(&cgroups::destroy),
-            hierarchy,
+            freezerHierarchy,
             cgroup(containerId),
             cgroups::DESTROY_TIMEOUT));
   }
 
   // Try to clean up using just the freezer cgroup.
   return cgroups::destroy(
-      hierarchy,
+      freezerHierarchy,
       cgroup(containerId),
       cgroups::DESTROY_TIMEOUT);
 }

http://git-wip-us.apache.org/repos/asf/mesos/blob/ac76392b/src/slave/containerizer/linux_launcher.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/linux_launcher.hpp 
b/src/slave/containerizer/linux_launcher.hpp
index f6112c9..f3b666d 100644
--- a/src/slave/containerizer/linux_launcher.hpp
+++ b/src/slave/containerizer/linux_launcher.hpp
@@ -54,11 +54,13 @@ public:
 private:
   LinuxLauncher(
       const Flags& flags,
-      const std::string& hierarchy);
+      const std::string& freezerHierarchy,
+      const Option<std::string>& systemdHierarchy);
 
   static const std::string subsystem;
   const Flags flags;
-  const std::string hierarchy;
+  const std::string freezerHierarchy;
+  const Option<std::string> systemdHierarchy;
 
   std::string cgroup(const ContainerID& containerId);
 

Reply via email to