You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by jo...@apache.org on 2015/09/24 06:18:33 UTC
[2/4] mesos git commit: Create and Start `mesos_executor.slice` in
LinuxLauncher on Systemd.
Create and Start `mesos_executor.slice` in LinuxLauncher on Systemd.
Review: https://reviews.apache.org/r/38635
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/76a4e18d
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/76a4e18d
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/76a4e18d
Branch: refs/heads/master
Commit: 76a4e18dab3d5a342b24775cf64898a9b6df3ef4
Parents: ac76392
Author: Joris Van Remoortere <jo...@gmail.com>
Authored: Wed Sep 23 17:46:45 2015 -0700
Committer: Joris Van Remoortere <jo...@gmail.com>
Committed: Wed Sep 23 20:56:46 2015 -0700
----------------------------------------------------------------------
src/linux/systemd.cpp | 117 ++++++++++++++++++++++++
src/linux/systemd.hpp | 75 +++++++++++++++
src/slave/containerizer/linux_launcher.cpp | 61 +++++++++++-
src/slave/containerizer/linux_launcher.hpp | 3 +
src/slave/flags.cpp | 5 +
src/slave/flags.hpp | 1 +
6 files changed, 261 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/76a4e18d/src/linux/systemd.cpp
----------------------------------------------------------------------
diff --git a/src/linux/systemd.cpp b/src/linux/systemd.cpp
index 7084e70..dde9e37 100644
--- a/src/linux/systemd.cpp
+++ b/src/linux/systemd.cpp
@@ -21,10 +21,14 @@
#include <string>
#include <vector>
+#include <process/once.hpp>
+
#include <stout/os.hpp>
#include <stout/strings.hpp>
#include <stout/try.hpp>
+using process::Once;
+
using std::string;
using std::vector;
@@ -32,6 +36,52 @@ namespace systemd {
int DELEGATE_MINIMUM_VERSION = 218;
+
+Flags::Flags()
+{
+ add(&Flags::runtime_directory,
+ "runtime_directory",
+ "The path to the systemd system run time directory\n",
+ "/run/systemd/system");
+
+ add(&Flags::cgroups_hierarchy,
+ "cgroups_hierarchy",
+ "The path to the cgroups hierarchy root\n",
+ "/sys/fs/cgroup");
+}
+
+
+static Flags* systemd_flags = NULL;
+
+
+const Flags& flags()
+{
+ return *CHECK_NOTNULL(systemd_flags);
+}
+
+
+Try<Nothing> initialize(const Flags& flags)
+{
+ static Once* initialized = new Once();
+
+ if (initialized->once()) {
+ return Nothing();
+ }
+
+ systemd_flags = new Flags(flags);
+
+ // If flags->runtime_directory doesn't exist, then we can't proceed.
+ if (!os::exists(CHECK_NOTNULL(systemd_flags)->runtime_directory)) {
+ return Error("Failed to locate systemd runtime directory: " +
+ CHECK_NOTNULL(systemd_flags)->runtime_directory);
+ }
+
+ initialized->done();
+
+ return Nothing();
+}
+
+
bool exists()
{
// This is static as the init system should not change while we are running.
@@ -97,4 +147,71 @@ bool exists()
return exists;
}
+
+Path runtimeDirectory()
+{
+ return Path(flags().runtime_directory);
+}
+
+
+Path hierarchy()
+{
+ return Path(path::join(flags().cgroups_hierarchy, "systemd"));
+}
+
+
+Try<Nothing> daemonReload()
+{
+ Try<std::string> daemonReload = os::shell("systemctl daemon-reload");
+ if (daemonReload.isError()) {
+ return Error("Failed to reload systemd daemon: " + daemonReload.error());
+ }
+
+ return Nothing();
+}
+
+namespace slices {
+
+bool exists(const Path& path)
+{
+ return os::exists(path);
+}
+
+
+Try<Nothing> create(const Path& path, const string& data)
+{
+ Try<Nothing> write = os::write(path, data);
+ if (write.isError()) {
+ return Error(
+ "Failed to write systemd slice `" + path.value + "`: " + write.error());
+ }
+
+ LOG(INFO) << "Created systemd slice: `" << path << "`";
+
+ Try<Nothing> reload = daemonReload();
+ if (reload.isError()) {
+ return Error("Failed to create systemd slice `" + path.value + "`: " +
+ reload.error());
+ }
+
+ return Nothing();
+}
+
+
+Try<Nothing> start(const std::string& name)
+{
+ Try<std::string> start = os::shell("systemctl start " + name);
+
+ if (start.isError()) {
+ return Error(
+ "Failed to start systemd slice `" + name + "`: " + start.error());
+ }
+
+ LOG(INFO) << "Started systemd slice `" << name << "`";
+
+ return Nothing();
+}
+
+} // namespace slices {
+
} // namespace systemd {
http://git-wip-us.apache.org/repos/asf/mesos/blob/76a4e18d/src/linux/systemd.hpp
----------------------------------------------------------------------
diff --git a/src/linux/systemd.hpp b/src/linux/systemd.hpp
index 81db822..7121967 100644
--- a/src/linux/systemd.hpp
+++ b/src/linux/systemd.hpp
@@ -19,9 +19,36 @@
#ifndef __SYSTEMD_HPP__
#define __SYSTEMD_HPP__
+#include <stout/flags.hpp>
+#include <stout/nothing.hpp>
+#include <stout/path.hpp>
+#include <stout/try.hpp>
+
namespace systemd {
/**
+ * Flags to initialize systemd state.
+ */
+class Flags : public virtual flags::FlagsBase
+{
+public:
+ Flags();
+
+ std::string runtime_directory;
+ std::string cgroups_hierarchy;
+};
+
+const Flags& flags();
+
+/**
+ * Initialized state for support of systemd functions in this file.
+ *
+ * @return Nothing if successful, otherwise Error.
+ */
+Try<Nothing> initialize(const Flags& flags);
+
+
+/**
* 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.
@@ -35,6 +62,54 @@ namespace systemd {
*/
bool exists();
+
+/**
+ * Returns the path to the runtime directory for systemd units.
+ */
+Path runtimeDirectory();
+
+
+/**
+ * Return the path to the systemd hierarchy.
+ */
+Path hierarchy();
+
+
+/**
+ * Runs systemctl daemon-reload.
+ *
+ * Used after updating configuration files.
+ *
+ * @return Nothing if successful, otherwise Error.
+ */
+Try<Nothing> daemonReload();
+
+namespace slices {
+
+/**
+ * Returns whether a systemd slice configuration file exists at the given path.
+ */
+bool exists(const Path& path);
+
+
+/**
+ * Creates a slice configuration with the provided contents at the given path.
+ *
+ * @param path The path at which to create the slice configurations file.
+ * @param data The contents of the configuration file.
+ *
+ * @return Nothing if successful, otherwise Error.
+ */
+Try<Nothing> create(const Path& path, const std::string& data);
+
+
+/**
+ * Starts the slice with the given name (via 'systemctl start <name>').
+ */
+Try<Nothing> start(const std::string& name);
+
+} // namespace slices {
+
} // namespace systemd {
#endif // __SYSTEMD_HPP__
http://git-wip-us.apache.org/repos/asf/mesos/blob/76a4e18d/src/slave/containerizer/linux_launcher.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/linux_launcher.cpp b/src/slave/containerizer/linux_launcher.cpp
index 55155ca..b746e54 100644
--- a/src/slave/containerizer/linux_launcher.cpp
+++ b/src/slave/containerizer/linux_launcher.cpp
@@ -110,11 +110,70 @@ Try<Launcher*> LinuxLauncher::create(const Flags& flags)
// slice. It then migrates executor pids into this slice before it "unpauses"
// the executor. This is the same pattern as the freezer.
+ // If this is a systemd environment, ensure that the
+ // `SYSTEMD_MESOS_EXECUTORS_SLICE` exists and is running.
+ // TODO(jmlvanre): Prevent racing between multiple agents for this creation
+ // logic.
+ if (systemd::exists()) {
+ systemd::Flags systemdFlags;
+ systemdFlags.runtime_directory = flags.systemd_runtime_directory;
+ systemdFlags.cgroups_hierarchy = flags.cgroups_hierarchy;
+ Try<Nothing> initialize = systemd::initialize(systemdFlags);
+ if (initialize.isError()) {
+ return Error("Failed to initialize systemd: " + initialize.error());
+ }
+
+ // Check whether the `SYSTEMD_MESOS_EXECUTORS_SLICE` already exists. Create
+ // it if it does not exist.
+ // We explicitly don't modify the file if it exists in case operators want
+ // to over-ride the settings for the slice that we provide when we create
+ // the `Unit` below.
+ const Path path(path::join(
+ systemd::runtimeDirectory(),
+ SYSTEMD_MESOS_EXECUTORS_SLICE));
+
+ if (!systemd::slices::exists(path)) {
+ // A simple systemd file to allow us to start a new slice.
+ string unit = "[Unit]\nDescription=Mesos Executors Slice\n";
+
+ Try<Nothing> create = systemd::slices::create(path, unit);
+
+ if (create.isError()) {
+ return Error("Failed to create systemd slice `" +
+ stringify(SYSTEMD_MESOS_EXECUTORS_SLICE) + "`: " +
+ create.error());
+ }
+ }
+
+ // Regardless of whether we created the file or it existed already, we
+ // `start` the executor slice. It is safe (a no-op) to `start` an already
+ // running slice.
+ Try<Nothing> start = systemd::slices::start(SYSTEMD_MESOS_EXECUTORS_SLICE);
+
+ if (start.isError()) {
+ return Error("Failed to start `" +
+ stringify(SYSTEMD_MESOS_EXECUTORS_SLICE) +
+ "`: " + start.error());
+ }
+
+ // Now the `SYSTEMD_MESOS_EXECUTORS_SLICE` is ready for us to assign any
+ // executors. We can verify that our cgroups assignments will work by
+ // testing the hierarchy.
+ Try<bool> exists = cgroups::exists(
+ systemd::hierarchy(),
+ SYSTEMD_MESOS_EXECUTORS_SLICE);
+
+ if (exists.isError() || !exists.get()) {
+ return Error("Failed to locate systemd cgroups hierarchy: " +
+ (exists.isError() ? exists.error() : "does not exist"));
+ }
+ }
+
return new LinuxLauncher(
flags,
freezerHierarchy.get(),
systemd::exists() ?
- Some(flags.cgroups_hierarchy + "/systemd") :
+ Some(systemd::hierarchy()) :
Option<std::string>::none());
}
http://git-wip-us.apache.org/repos/asf/mesos/blob/76a4e18d/src/slave/containerizer/linux_launcher.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/linux_launcher.hpp b/src/slave/containerizer/linux_launcher.hpp
index f3b666d..35b3315 100644
--- a/src/slave/containerizer/linux_launcher.hpp
+++ b/src/slave/containerizer/linux_launcher.hpp
@@ -25,6 +25,9 @@ namespace mesos {
namespace internal {
namespace slave {
+// TODO(jmlvanre): We may want to allow this to be configured.
+static const char SYSTEMD_MESOS_EXECUTORS_SLICE[] = "mesos_executors.slice";
+
// Launcher for Linux systems with cgroups. Uses a freezer cgroup to
// track pids.
class LinuxLauncher : public Launcher
http://git-wip-us.apache.org/repos/asf/mesos/blob/76a4e18d/src/slave/flags.cpp
----------------------------------------------------------------------
diff --git a/src/slave/flags.cpp b/src/slave/flags.cpp
index 6164b4b..ab3b0e1 100644
--- a/src/slave/flags.cpp
+++ b/src/slave/flags.cpp
@@ -316,6 +316,11 @@ mesos::internal::slave::Flags::Flags()
"normal containers (non-revocable cpu). Currently only\n"
"supported by the cgroups/cpu isolator.",
true);
+
+ add(&Flags::systemd_runtime_directory,
+ "systemd_runtime_directory",
+ "The path to the systemd system run time directory\n",
+ "/run/systemd/system");
#endif
add(&Flags::firewall_rules,
http://git-wip-us.apache.org/repos/asf/mesos/blob/76a4e18d/src/slave/flags.hpp
----------------------------------------------------------------------
diff --git a/src/slave/flags.hpp b/src/slave/flags.hpp
index b8d6bb4..bbf8171 100644
--- a/src/slave/flags.hpp
+++ b/src/slave/flags.hpp
@@ -88,6 +88,7 @@ public:
Duration perf_interval;
Duration perf_duration;
bool revocable_cpu_low_priority;
+ std::string systemd_runtime_directory;
#endif
Option<Firewall> firewall_rules;
Option<Path> credential;