You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by ji...@apache.org on 2016/08/20 21:18:33 UTC

mesos git commit: Implemented `DevicesSubsystem`.

Repository: mesos
Updated Branches:
  refs/heads/master ee4f8a251 -> 67c36f6f9


Implemented `DevicesSubsystem`.

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


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

Branch: refs/heads/master
Commit: 67c36f6f9071f970bd913b38838248adb9c109ab
Parents: ee4f8a2
Author: haosdent huang <ha...@gmail.com>
Authored: Sat Aug 20 09:40:25 2016 -0700
Committer: Jie Yu <yu...@gmail.com>
Committed: Sat Aug 20 14:18:16 2016 -0700

----------------------------------------------------------------------
 src/CMakeLists.txt                              |   1 +
 src/Makefile.am                                 |   2 +
 .../mesos/isolators/cgroups/cgroups.cpp         |   1 +
 .../mesos/isolators/cgroups/constants.hpp       |   1 +
 .../mesos/isolators/cgroups/subsystem.cpp       |   2 +
 .../isolators/cgroups/subsystems/devices.cpp    | 165 +++++++++++++++++++
 .../isolators/cgroups/subsystems/devices.hpp    |  67 ++++++++
 7 files changed, 239 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/67c36f6f/src/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 85eb2b8..ff51705 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -169,6 +169,7 @@ set(LINUX_SRC
   slave/containerizer/mesos/isolators/cgroups/subsystem.cpp
   slave/containerizer/mesos/isolators/cgroups/subsystems/cpu.cpp
   slave/containerizer/mesos/isolators/cgroups/subsystems/cpuacct.cpp
+  slave/containerizer/mesos/isolators/cgroups/subsystems/devices.cpp
   slave/containerizer/mesos/isolators/docker/runtime.cpp
   slave/containerizer/mesos/isolators/docker/volume/driver.cpp
   slave/containerizer/mesos/isolators/docker/volume/isolator.cpp

http://git-wip-us.apache.org/repos/asf/mesos/blob/67c36f6f/src/Makefile.am
----------------------------------------------------------------------
diff --git a/src/Makefile.am b/src/Makefile.am
index d0f937d..61c941f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1053,6 +1053,7 @@ MESOS_LINUX_FILES =							\
   slave/containerizer/mesos/isolators/cgroups/subsystem.cpp		\
   slave/containerizer/mesos/isolators/cgroups/subsystems/cpu.cpp	\
   slave/containerizer/mesos/isolators/cgroups/subsystems/cpuacct.cpp	\
+  slave/containerizer/mesos/isolators/cgroups/subsystems/devices.cpp	\
   slave/containerizer/mesos/isolators/docker/runtime.cpp		\
   slave/containerizer/mesos/isolators/docker/volume/isolator.cpp	\
   slave/containerizer/mesos/isolators/filesystem/linux.cpp		\
@@ -1088,6 +1089,7 @@ MESOS_LINUX_FILES +=							\
   slave/containerizer/mesos/isolators/cgroups/subsystem.hpp		\
   slave/containerizer/mesos/isolators/cgroups/subsystems/cpu.hpp	\
   slave/containerizer/mesos/isolators/cgroups/subsystems/cpuacct.hpp	\
+  slave/containerizer/mesos/isolators/cgroups/subsystems/devices.hpp	\
   slave/containerizer/mesos/isolators/docker/runtime.hpp		\
   slave/containerizer/mesos/isolators/docker/volume/isolator.hpp	\
   slave/containerizer/mesos/isolators/filesystem/linux.hpp		\

http://git-wip-us.apache.org/repos/asf/mesos/blob/67c36f6f/src/slave/containerizer/mesos/isolators/cgroups/cgroups.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/cgroups/cgroups.cpp b/src/slave/containerizer/mesos/isolators/cgroups/cgroups.cpp
index 1b84a56..5be2b71 100644
--- a/src/slave/containerizer/mesos/isolators/cgroups/cgroups.cpp
+++ b/src/slave/containerizer/mesos/isolators/cgroups/cgroups.cpp
@@ -77,6 +77,7 @@ Try<Isolator*> CgroupsIsolatorProcess::create(const Flags& flags)
   multihashmap<string, string> isolatorMap = {
     {"cpu", CGROUP_SUBSYSTEM_CPU_NAME},
     {"cpu", CGROUP_SUBSYSTEM_CPUACCT_NAME},
+    {"devices", CGROUP_SUBSYSTEM_DEVICES_NAME},
   };
 
   foreach (string isolator, strings::tokenize(flags.isolation, ",")) {

http://git-wip-us.apache.org/repos/asf/mesos/blob/67c36f6f/src/slave/containerizer/mesos/isolators/cgroups/constants.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/cgroups/constants.hpp b/src/slave/containerizer/mesos/isolators/cgroups/constants.hpp
index 3146cc6..4a7b556 100644
--- a/src/slave/containerizer/mesos/isolators/cgroups/constants.hpp
+++ b/src/slave/containerizer/mesos/isolators/cgroups/constants.hpp
@@ -41,6 +41,7 @@ const Bytes MIN_MEMORY = Megabytes(32);
 // Subsystem names.
 const std::string CGROUP_SUBSYSTEM_CPU_NAME = "cpu";
 const std::string CGROUP_SUBSYSTEM_CPUACCT_NAME = "cpuacct";
+const std::string CGROUP_SUBSYSTEM_DEVICES_NAME = "devices";
 
 } // namespace slave {
 } // namespace internal {

http://git-wip-us.apache.org/repos/asf/mesos/blob/67c36f6f/src/slave/containerizer/mesos/isolators/cgroups/subsystem.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/cgroups/subsystem.cpp b/src/slave/containerizer/mesos/isolators/cgroups/subsystem.cpp
index 9789cf6..df701d2 100644
--- a/src/slave/containerizer/mesos/isolators/cgroups/subsystem.cpp
+++ b/src/slave/containerizer/mesos/isolators/cgroups/subsystem.cpp
@@ -22,6 +22,7 @@
 
 #include "slave/containerizer/mesos/isolators/cgroups/subsystems/cpu.hpp"
 #include "slave/containerizer/mesos/isolators/cgroups/subsystems/cpuacct.hpp"
+#include "slave/containerizer/mesos/isolators/cgroups/subsystems/devices.hpp"
 
 using process::Future;
 using process::Owned;
@@ -41,6 +42,7 @@ Try<Owned<Subsystem>> Subsystem::create(
     creators = {
     {CGROUP_SUBSYSTEM_CPU_NAME, &CpuSubsystem::create},
     {CGROUP_SUBSYSTEM_CPUACCT_NAME, &CpuacctSubsystem::create},
+    {CGROUP_SUBSYSTEM_DEVICES_NAME, &DevicesSubsystem::create},
   };
 
   if (!creators.contains(name)) {

http://git-wip-us.apache.org/repos/asf/mesos/blob/67c36f6f/src/slave/containerizer/mesos/isolators/cgroups/subsystems/devices.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/cgroups/subsystems/devices.cpp b/src/slave/containerizer/mesos/isolators/cgroups/subsystems/devices.cpp
new file mode 100644
index 0000000..0e83aa1
--- /dev/null
+++ b/src/slave/containerizer/mesos/isolators/cgroups/subsystems/devices.cpp
@@ -0,0 +1,165 @@
+// 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 <process/id.hpp>
+
+#include <stout/nothing.hpp>
+#include <stout/try.hpp>
+
+#include "linux/cgroups.hpp"
+
+#include "slave/containerizer/mesos/isolators/cgroups/subsystems/devices.hpp"
+
+using cgroups::devices::Entry;
+
+using process::Failure;
+using process::Future;
+using process::Owned;
+
+using std::string;
+
+namespace mesos {
+namespace internal {
+namespace slave {
+
+// The default list of devices to whitelist when device isolation is
+// turned on. The full list of devices can be found here:
+// https://www.kernel.org/doc/Documentation/devices.txt
+//
+// Device whitelisting is described here:
+// https://www.kernel.org/doc/Documentation/cgroup-v1/devices.txt
+static const char* DEFAULT_WHITELIST_ENTRIES[] = {
+  "c *:* m",      // Make new character devices.
+  "b *:* m",      // Make new block devices.
+  "c 5:1 rwm",    // /dev/console
+  "c 4:0 rwm",    // /dev/tty0
+  "c 4:1 rwm",    // /dev/tty1
+  "c 136:* rwm",  // /dev/pts/*
+  "c 5:2 rwm",    // /dev/ptmx
+  "c 10:200 rwm", // /dev/net/tun
+  "c 1:3 rwm",    // /dev/null
+  "c 1:5 rwm",    // /dev/zero
+  "c 1:7 rwm",    // /dev/full
+  "c 5:0 rwm",    // /dev/tty
+  "c 1:9 rwm",    // /dev/urandom
+  "c 1:8 rwm",    // /dev/random
+};
+
+
+Try<Owned<Subsystem>> DevicesSubsystem::create(
+    const Flags& flags,
+    const string& hierarchy)
+{
+  return Owned<Subsystem>(new DevicesSubsystem(flags, hierarchy));
+}
+
+
+DevicesSubsystem::DevicesSubsystem(
+    const Flags& _flags,
+    const string& _hierarchy)
+  : ProcessBase(process::ID::generate("cgroups-devices-subsystem")),
+    Subsystem(_flags, _hierarchy) {}
+
+
+Future<Nothing> DevicesSubsystem::recover(const ContainerID& containerId)
+{
+  if (containerIds.contains(containerId)) {
+    return Failure(
+        "The subsystem '" + name() + "' of container " +
+        stringify(containerId) + " has already been recovered");
+  }
+
+  containerIds.insert(containerId);
+
+  return Nothing();
+}
+
+
+Future<Nothing> DevicesSubsystem::prepare(const ContainerID& containerId)
+{
+  if (containerIds.contains(containerId)) {
+    return Failure("The subsystem '" + name() + "' has already been prepared");
+  }
+
+  // When a devices cgroup is first created, its whitelist inherits
+  // all devices from its parent's whitelist (i.e., "a *:* rwm" by
+  // default). In theory, we should be able to add and remove devices
+  // from the whitelist by writing to the respective `devices.allow`
+  // and `devices.deny` files associated with the cgroup. However, the
+  // semantics of the whitelist are such that writing to the deny file
+  // will only remove entries in the whitelist that are explicitly
+  // listed in there (i.e., denying "b 1:3 rwm" when the whitelist
+  // only contains "a *:* rwm" will not modify the whitelist because
+  // "b 1:3 rwm" is not explicitly listed). Although the whitelist
+  // doesn't change, access to the device is still denied as expected
+  // (there is just no way of querying the system to detect it).
+  // Because of this, we first deny access to all devices and
+  // selectively add some back in so we can control the entries in the
+  // whitelist explicitly.
+  cgroups::devices::Entry all;
+  all.selector.type = Entry::Selector::Type::ALL;
+  all.selector.major = None();
+  all.selector.minor = None();
+  all.access.read = true;
+  all.access.write = true;
+  all.access.mknod = true;
+
+  Try<Nothing> deny = cgroups::devices::deny(
+      hierarchy,
+      path::join(flags.cgroups_root, containerId.value()),
+      all);
+
+  if (deny.isError()) {
+    return Failure("Failed to deny all devices: " + deny.error());
+  }
+
+  foreach (const char* _entry, DEFAULT_WHITELIST_ENTRIES) {
+    Try<cgroups::devices::Entry> entry =
+      cgroups::devices::Entry::parse(_entry);
+
+    CHECK_SOME(entry);
+
+    Try<Nothing> allow = cgroups::devices::allow(
+        hierarchy, path::join(flags.cgroups_root, containerId.value()),
+        entry.get());
+
+    if (allow.isError()) {
+      return Failure("Failed to whitelist default device "
+                     "'" + stringify(entry.get()) + "': " + allow.error());
+    }
+  }
+
+  containerIds.insert(containerId);
+
+  return Nothing();
+}
+
+
+Future<Nothing> DevicesSubsystem::cleanup(const ContainerID& containerId)
+{
+  // Multiple calls may occur during test clean up.
+  if (!containerIds.contains(containerId)) {
+    return Failure("Unknown container");
+  }
+
+  containerIds.erase(containerId);
+
+  return Nothing();
+}
+
+} // namespace slave {
+} // namespace internal {
+} // namespace mesos {

http://git-wip-us.apache.org/repos/asf/mesos/blob/67c36f6f/src/slave/containerizer/mesos/isolators/cgroups/subsystems/devices.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/cgroups/subsystems/devices.hpp b/src/slave/containerizer/mesos/isolators/cgroups/subsystems/devices.hpp
new file mode 100644
index 0000000..b5d5ed2
--- /dev/null
+++ b/src/slave/containerizer/mesos/isolators/cgroups/subsystems/devices.hpp
@@ -0,0 +1,67 @@
+// 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 __CGROUPS_ISOLATOR_SUBSYSTEMS_DEVICES_HPP__
+#define __CGROUPS_ISOLATOR_SUBSYSTEMS_DEVICES_HPP__
+
+#include <string>
+
+#include <process/owned.hpp>
+
+#include <stout/hashset.hpp>
+#include <stout/try.hpp>
+
+#include "slave/flags.hpp"
+
+#include "slave/containerizer/mesos/isolators/cgroups/constants.hpp"
+#include "slave/containerizer/mesos/isolators/cgroups/subsystem.hpp"
+
+namespace mesos {
+namespace internal {
+namespace slave {
+
+/**
+ * Represent cgroups devices subsystem.
+ */
+class DevicesSubsystem: public Subsystem
+{
+public:
+  static Try<process::Owned<Subsystem>> create(
+      const Flags& flags,
+      const std::string& hierarchy);
+
+  virtual ~DevicesSubsystem() {}
+
+  virtual std::string name() const
+  {
+    return CGROUP_SUBSYSTEM_DEVICES_NAME;
+  }
+
+  virtual process::Future<Nothing> prepare(const ContainerID& containerId);
+  virtual process::Future<Nothing> recover(const ContainerID& containerId);
+  virtual process::Future<Nothing> cleanup(const ContainerID& containerId);
+
+private:
+  DevicesSubsystem(const Flags& flags, const std::string& hierarchy);
+
+  hashset<ContainerID> containerIds;
+};
+
+} // namespace slave {
+} // namespace internal {
+} // namespace mesos {
+
+#endif // __CGROUPS_ISOLATOR_SUBSYSTEMS_DEVICES_HPP__