You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by nn...@apache.org on 2014/10/22 20:28:05 UTC

git commit: Added sample isolator module.

Repository: mesos
Updated Branches:
  refs/heads/master 914b99018 -> 6e77b3529


Added sample isolator module.

Created CPU and Memory isolation modules based on Posix CPU/Memory
Isolators. These modules are also hooked up to the relevant Isolator
tests using the typed test mechanism. It also paves the way for future
integration with custom modules specified on the command line.

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


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

Branch: refs/heads/master
Commit: 6e77b3529bfe5cd08885ce71afcad59f56cd353f
Parents: 914b990
Author: Kapil Arya <ka...@mesosphere.io>
Authored: Wed Oct 22 10:59:51 2014 -0700
Committer: Niklas Q. Nielsen <ni...@mesosphere.io>
Committed: Wed Oct 22 10:59:51 2014 -0700

----------------------------------------------------------------------
 src/Makefile.am                       |  9 +++
 src/examples/test_isolator_module.cpp | 84 +++++++++++++++++++++++++++
 src/module/isolator.hpp               | 64 ++++++++++++++++++++
 src/module/manager.cpp                |  1 +
 src/tests/isolator_tests.cpp          | 20 ++++---
 src/tests/main.cpp                    |  9 +++
 src/tests/module.cpp                  | 93 ++++++++++++++++++++++++++++++
 src/tests/module.hpp                  | 72 +++++++++++++++++++++++
 src/tests/module_tests.cpp            | 18 +++++-
 9 files changed, 360 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/6e77b352/src/Makefile.am
----------------------------------------------------------------------
diff --git a/src/Makefile.am b/src/Makefile.am
index c44a9ad..2617f77 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -422,6 +422,7 @@ libmesos_no_3rdparty_la_SOURCES +=					\
 	master/registrar.hpp						\
 	master/sorter.hpp						\
 	messages/messages.hpp						\
+	module/isolator.hpp						\
 	module/manager.hpp						\
 	slave/constants.hpp						\
 	slave/flags.hpp							\
@@ -449,6 +450,7 @@ libmesos_no_3rdparty_la_SOURCES +=					\
 	tests/flags.hpp							\
 	tests/isolator.hpp						\
 	tests/mesos.hpp							\
+	tests/module.hpp							\
 	tests/script.hpp						\
 	tests/utils.hpp							\
 	tests/zookeeper.hpp						\
@@ -1140,6 +1142,12 @@ libexamplemodule_la_SOURCES = examples/example_module_impl.cpp
 libexamplemodule_la_CPPFLAGS = $(MESOS_CPPFLAGS)
 libexamplemodule_la_LDFLAGS = -release $(PACKAGE_VERSION) -shared
 
+# Library containing test CPU and memory isolator modules.
+lib_LTLIBRARIES += libtestisolator.la
+libtestisolator_la_SOURCES = examples/test_isolator_module.cpp
+libtestisolator_la_CPPFLAGS = $(MESOS_CPPFLAGS)
+libtestisolator_la_LDFLAGS = -release $(PACKAGE_VERSION) -shared
+
 mesos_tests_SOURCES =				\
   tests/allocator_tests.cpp			\
   tests/attributes_tests.cpp			\
@@ -1169,6 +1177,7 @@ mesos_tests_SOURCES =				\
   tests/master_slave_reconciliation_tests.cpp	\
   tests/master_tests.cpp			\
   tests/mesos.cpp				\
+  tests/module.cpp				\
   tests/module_tests.cpp			\
   tests/monitor_tests.cpp			\
   tests/partition_tests.cpp			\

http://git-wip-us.apache.org/repos/asf/mesos/blob/6e77b352/src/examples/test_isolator_module.cpp
----------------------------------------------------------------------
diff --git a/src/examples/test_isolator_module.cpp b/src/examples/test_isolator_module.cpp
new file mode 100644
index 0000000..2d6b427
--- /dev/null
+++ b/src/examples/test_isolator_module.cpp
@@ -0,0 +1,84 @@
+/**
+ * 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 <mesos/module.hpp>
+
+#include <stout/try.hpp>
+
+#include "module/isolator.hpp"
+
+#include "slave/containerizer/isolator.hpp"
+#include "slave/containerizer/isolators/posix.hpp"
+#include "slave/flags.hpp"
+
+using mesos::internal::slave::Flags;
+using mesos::internal::slave::Isolator;
+using mesos::internal::slave::PosixCpuIsolatorProcess;
+using mesos::internal::slave::PosixMemIsolatorProcess;
+
+
+// The sole purpose of this function is just to exercise the
+// compatibility logic.
+static bool compatible()
+{
+  return true;
+}
+
+
+static Isolator* createCpuIsolator()
+{
+  Flags flags;
+  Try<Isolator*> result = PosixCpuIsolatorProcess::create(flags);
+  if (result.isError()) {
+    return NULL;
+  }
+  return result.get();
+}
+
+
+static Isolator* createMemIsolator()
+{
+  Flags flags;
+  Try<Isolator*> result = PosixMemIsolatorProcess::create(flags);
+  if (result.isError()) {
+    return NULL;
+  }
+  return result.get();
+}
+
+
+// Declares a CPU Isolator module named 'testCpuIsolator'.
+mesos::modules::Module<Isolator> org_apache_mesos_TestCpuIsolator(
+    MESOS_MODULE_API_VERSION,
+    MESOS_VERSION,
+    "Apache Mesos",
+    "modules@mesos.apache.org",
+    "Test CPU Isolator module.",
+    compatible,
+    createCpuIsolator);
+
+
+// Declares a Memory Isolator module named 'testMemIsolator'.
+mesos::modules::Module<Isolator> org_apache_mesos_TestMemIsolator(
+    MESOS_MODULE_API_VERSION,
+    MESOS_VERSION,
+    "Apache Mesos",
+    "modules@mesos.apache.org",
+    "Test Memory Isolator module.",
+    NULL, // Do not perform any compatibility check.
+    createMemIsolator);

http://git-wip-us.apache.org/repos/asf/mesos/blob/6e77b352/src/module/isolator.hpp
----------------------------------------------------------------------
diff --git a/src/module/isolator.hpp b/src/module/isolator.hpp
new file mode 100644
index 0000000..fc78b07
--- /dev/null
+++ b/src/module/isolator.hpp
@@ -0,0 +1,64 @@
+/**
+ * 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 __MODULE_ISOLATOR_HPP__
+#define __MODULE_ISOLATOR_HPP__
+
+#include <mesos/module.hpp>
+
+#include "slave/containerizer/isolator.hpp"
+
+namespace mesos {
+namespace modules {
+
+template<>
+inline const char* kind<mesos::internal::slave::Isolator>()
+{
+  return "Isolator";
+}
+
+
+template <>
+struct Module<mesos::internal::slave::Isolator> : ModuleBase
+{
+  Module(
+      const char* _moduleApiVersion,
+      const char* _mesosVersion,
+      const char* _authorName,
+      const char* _authorEmail,
+      const char* _description,
+      bool (*_compatible)(),
+      mesos::internal::slave::Isolator* (*_create)())
+    : ModuleBase(
+        _moduleApiVersion,
+        _mesosVersion,
+        mesos::modules::kind<mesos::internal::slave::Isolator>(),
+        _authorName,
+        _authorEmail,
+        _description,
+        _compatible),
+      create(_create)
+  { }
+
+  mesos::internal::slave::Isolator* (*create)();
+};
+
+} // namespace modules {
+} // namespace mesos {
+
+#endif // __MODULE_ISOLATOR_HPP__

http://git-wip-us.apache.org/repos/asf/mesos/blob/6e77b352/src/module/manager.cpp
----------------------------------------------------------------------
diff --git a/src/module/manager.cpp b/src/module/manager.cpp
index 1e71e1f..63056a4 100644
--- a/src/module/manager.cpp
+++ b/src/module/manager.cpp
@@ -57,6 +57,7 @@ void ModuleManager::initialize()
   // under development.
 
   kindToVersion["TestModule"] = MESOS_VERSION;
+  kindToVersion["Isolator"] = MESOS_VERSION;
 
   // What happens then when Mesos is built with a certain version,
   // 'kindToVersion' states a certain other minimum version, and a

http://git-wip-us.apache.org/repos/asf/mesos/blob/6e77b352/src/tests/isolator_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/isolator_tests.cpp b/src/tests/isolator_tests.cpp
index c38f876..52b38a3 100644
--- a/src/tests/isolator_tests.cpp
+++ b/src/tests/isolator_tests.cpp
@@ -38,6 +38,8 @@
 #include "master/master.hpp"
 #include "master/detector.hpp"
 
+#include "module/isolator.hpp"
+
 #include "slave/flags.hpp"
 #include "slave/slave.hpp"
 
@@ -58,6 +60,7 @@
 #endif // __linux__
 
 #include "tests/mesos.hpp"
+#include "tests/module.hpp"
 #include "tests/utils.hpp"
 
 using namespace mesos;
@@ -119,12 +122,12 @@ static int childSetup(int pipes[2])
 template <typename T>
 class CpuIsolatorTest : public MesosTest {};
 
+typedef ::testing::Types<
+    PosixCpuIsolatorProcess,
 #ifdef __linux__
-typedef ::testing::Types<PosixCpuIsolatorProcess,
-                         CgroupsCpushareIsolatorProcess> CpuIsolatorTypes;
-#else
-typedef ::testing::Types<PosixCpuIsolatorProcess> CpuIsolatorTypes;
+    CgroupsCpushareIsolatorProcess,
 #endif // __linux__
+    tests::Module<Isolator, TestCpuIsolator>> CpuIsolatorTypes;
 
 TYPED_TEST_CASE(CpuIsolatorTest, CpuIsolatorTypes);
 
@@ -516,16 +519,15 @@ TEST_F(LimitedCpuIsolatorTest, ROOT_CGROUPS_Cfs_Big_Quota)
 
 #endif // __linux__
 
-
 template <typename T>
 class MemIsolatorTest : public MesosTest {};
 
+typedef ::testing::Types<
+    PosixMemIsolatorProcess,
 #ifdef __linux__
-typedef ::testing::Types<PosixMemIsolatorProcess,
-                         CgroupsMemIsolatorProcess> MemIsolatorTypes;
-#else
-typedef ::testing::Types<PosixMemIsolatorProcess> MemIsolatorTypes;
+    CgroupsMemIsolatorProcess,
 #endif // __linux__
+    tests::Module<Isolator, TestMemIsolator>> MemIsolatorTypes;
 
 TYPED_TEST_CASE(MemIsolatorTest, MemIsolatorTypes);
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/6e77b352/src/tests/main.cpp
----------------------------------------------------------------------
diff --git a/src/tests/main.cpp b/src/tests/main.cpp
index 90a7ddc..fc83fd0 100644
--- a/src/tests/main.cpp
+++ b/src/tests/main.cpp
@@ -37,6 +37,7 @@
 
 #include "tests/environment.hpp"
 #include "tests/flags.hpp"
+#include "tests/module.hpp"
 
 using namespace mesos::internal;
 using namespace mesos::internal::tests;
@@ -84,6 +85,14 @@ int main(int argc, char** argv)
     exit(1);
   }
 
+  // Initialize Modules.
+  // TODO(karya): Add --modules flag to populate "modules".
+  Option<Modules> modules;
+  Try<Nothing> result = tests::initModules(modules);
+  if (result.isError()) {
+    EXIT(1) << "Error initializing modules: " << result.error();
+  }
+
   // Initialize libprocess.
   process::initialize();
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/6e77b352/src/tests/module.cpp
----------------------------------------------------------------------
diff --git a/src/tests/module.cpp b/src/tests/module.cpp
new file mode 100644
index 0000000..45becad
--- /dev/null
+++ b/src/tests/module.cpp
@@ -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.
+ */
+
+#include <string>
+
+#include <stout/hashmap.hpp>
+#include <stout/os.hpp>
+#include <stout/path.hpp>
+
+#include "messages/messages.hpp"
+#include "module/manager.hpp"
+
+#include "tests/flags.hpp"
+#include "tests/module.hpp"
+
+using std::string;
+
+using namespace mesos;
+using namespace mesos::internal;
+using namespace mesos::internal::tests;
+using namespace mesos::modules;
+
+static hashmap<ModuleID, string> moduleNames;
+
+
+static void addModule(
+    Modules::Library* library,
+    ModuleID moduleId,
+    string moduleName)
+{
+  moduleNames[moduleId] = moduleName;
+  library->add_modules(moduleNames[moduleId]);
+}
+
+
+// Add available Isolator modules.
+static void addIsolatorModules(Modules& modules)
+{
+  const string libraryPath = path::join(
+      tests::flags.build_dir,
+      "src",
+      ".libs",
+      os::libraries::expandName("testisolator"));
+
+  // Now add our test CPU and Memory isolator modules.
+  Modules::Library* library = modules.add_libraries();
+  library->set_file(libraryPath);
+
+  // To add a new module from this library, create a new ModuleID enum
+  // and tie it with a module name.
+  addModule(library, TestCpuIsolator, "org_apache_mesos_TestCpuIsolator");
+  addModule(library, TestMemIsolator, "org_apache_mesos_TestMemIsolator");
+}
+
+
+Try<Nothing> tests::initModules(const Option<Modules>& modules)
+{
+  // First get the user provided modules.
+  Modules mergedModules;
+  if (modules.isSome()) {
+    mergedModules = modules.get();
+  }
+
+  // Add isolator modules from testisolator library.
+  addIsolatorModules(mergedModules);
+
+  return ModuleManager::load(mergedModules);
+}
+
+
+// Mapping from module ID to the actual module name.
+Try<string> tests::getModuleName(ModuleID id)
+{
+  if (!moduleNames.contains(id)) {
+    return Error("Module '" + stringify(id) + "' not found");
+  }
+  return moduleNames[id];
+}

http://git-wip-us.apache.org/repos/asf/mesos/blob/6e77b352/src/tests/module.hpp
----------------------------------------------------------------------
diff --git a/src/tests/module.hpp b/src/tests/module.hpp
new file mode 100644
index 0000000..7970c28
--- /dev/null
+++ b/src/tests/module.hpp
@@ -0,0 +1,72 @@
+/**
+ * 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 __TESTS_MODULE_HPP__
+#define __TESTS_MODULE_HPP__
+
+#include <string>
+
+#include <stout/try.hpp>
+
+#include "logging/flags.hpp"
+#include "messages/messages.hpp"
+#include "module/manager.hpp"
+
+#include "tests/mesos.hpp"
+
+namespace mesos {
+namespace internal {
+namespace tests {
+
+// The ModuleID is used by typed tests to specify the specific module
+// name for the test instance.  Ideally, we would have passed the
+// module name itself, but templates do not allow string literals as
+// template parameters.
+enum ModuleID
+{
+  TestMemIsolator,
+  TestCpuIsolator
+};
+
+
+Try<Nothing> initModules(const Option<Modules>& modules);
+
+Try<std::string> getModuleName(ModuleID id);
+
+
+template <typename T, ModuleID N>
+class Module
+{
+public:
+  // Create is used by the type_param'ed tests.  T here denotes the
+  // module type, whereas N denotes the module name.
+  static Try<T*> create(logging::Flags flags)
+  {
+    Try<std::string> moduleName = getModuleName(N);
+    if (moduleName.isError()) {
+      return Error(moduleName.error());
+    }
+    return mesos::modules::ModuleManager::create<T>(moduleName.get());
+  }
+};
+
+} // namespace tests {
+} // namespace internal {
+} // namespace mesos {
+
+#endif // __TESTS_MODULE_HPP__

http://git-wip-us.apache.org/repos/asf/mesos/blob/6e77b352/src/tests/module_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/module_tests.cpp b/src/tests/module_tests.cpp
index c695bf7..45125d8 100644
--- a/src/tests/module_tests.cpp
+++ b/src/tests/module_tests.cpp
@@ -22,8 +22,9 @@
 #include <stout/os.hpp>
 
 #include "examples/test_module.hpp"
-
+#include "module/isolator.hpp"
 #include "module/manager.hpp"
+#include "slave/containerizer/isolator.hpp"
 
 #include "tests/flags.hpp"
 #include "tests/mesos.hpp"
@@ -32,6 +33,7 @@ using std::string;
 
 using namespace mesos;
 using namespace mesos::internal;
+using namespace mesos::internal::slave;
 using namespace mesos::internal::tests;
 using namespace mesos::modules;
 
@@ -183,6 +185,20 @@ TEST_F(ModuleTest, InvalidModuleKind)
 }
 
 
+// Verify that loading a module of different kind fails.
+TEST_F(ModuleTest, ModuleKindMismatch)
+{
+  EXPECT_SOME(ModuleManager::load(defaultModules));
+
+  EXPECT_TRUE(ModuleManager::contains<TestModule>(DEFAULT_MODULE_NAME));
+  EXPECT_FALSE(ModuleManager::contains<Isolator>(DEFAULT_MODULE_NAME));
+
+  module = ModuleManager::create<TestModule>(DEFAULT_MODULE_NAME);
+  EXPECT_SOME(module);
+  EXPECT_ERROR(ModuleManager::create<Isolator>(DEFAULT_MODULE_NAME));
+}
+
+
 // Test for correct author name, author email and library description.
 TEST_F(ModuleTest, AuthorInfoTest)
 {