You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by be...@apache.org on 2014/05/03 07:59:14 UTC

git commit: Introduced MesosContainerizer::create.

Repository: mesos
Updated Branches:
  refs/heads/master f88d5dc1f -> 103009625


Introduced MesosContainerizer::create.

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


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

Branch: refs/heads/master
Commit: 1030096255cea003f05f0a28b0833575f9062afe
Parents: f88d5dc
Author: Benjamin Hindman <be...@gmail.com>
Authored: Wed Apr 9 14:23:32 2014 -0600
Committer: Benjamin Hindman <be...@gmail.com>
Committed: Fri May 2 22:58:26 2014 -0700

----------------------------------------------------------------------
 src/slave/containerizer/containerizer.cpp       |  70 +-----
 src/slave/containerizer/mesos_containerizer.cpp |  77 ++++++
 src/slave/containerizer/mesos_containerizer.hpp |   2 +
 src/tests/containerizer_tests.cpp               |   9 +-
 src/tests/slave_recovery_tests.cpp              | 239 ++++++++++---------
 src/tests/slave_tests.cpp                       |   4 +-
 6 files changed, 218 insertions(+), 183 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/10300962/src/slave/containerizer/containerizer.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/containerizer.cpp b/src/slave/containerizer/containerizer.cpp
index 374a778..922ae17 100644
--- a/src/slave/containerizer/containerizer.cpp
+++ b/src/slave/containerizer/containerizer.cpp
@@ -40,12 +40,6 @@
 #include "slave/containerizer/mesos_containerizer.hpp"
 #include "slave/containerizer/external_containerizer.hpp"
 
-#include "slave/containerizer/isolators/posix.hpp"
-#ifdef __linux__
-#include "slave/containerizer/isolators/cgroups/cpushare.hpp"
-#include "slave/containerizer/isolators/cgroups/mem.hpp"
-#endif // __linux__
-
 using std::map;
 using std::string;
 using std::vector;
@@ -156,70 +150,20 @@ Try<Resources> Containerizer::resources(const Flags& flags)
 }
 
 
-Try<Containerizer*> Containerizer::create(
-    const Flags& flags,
-    bool local)
+Try<Containerizer*> Containerizer::create(const Flags& flags, bool local)
 {
-  string isolation;
-  if (flags.isolation == "process") {
-    LOG(WARNING) << "The 'process' isolation flag is deprecated, "
-                 << "please update your flags to"
-                 << " '--isolation=posix/cpu,posix/mem'.";
-    isolation = "posix/cpu,posix/mem";
-  } else if (flags.isolation == "cgroups") {
-    LOG(WARNING) << "The 'cgroups' isolation flag is deprecated, "
-                 << "please update your flags to"
-                 << " '--isolation=cgroups/cpu,cgroups/mem'.";
-    isolation = "cgroups/cpu,cgroups/mem";
-  } else {
-    isolation = flags.isolation;
-  }
-
-  LOG(INFO) << "Using isolation: " << isolation;
-
-  if (isolation == "external") {
+  if (flags.isolation == "external") {
     return new ExternalContainerizer(flags);
   }
 
-  // Create a MesosContainerizerProcess using isolators and a launcher.
-  hashmap<std::string, Try<Isolator*> (*)(const Flags&)> creators;
-
-  creators["posix/cpu"]   = &PosixCpuIsolatorProcess::create;
-  creators["posix/mem"]   = &PosixMemIsolatorProcess::create;
-#ifdef __linux__
-  creators["cgroups/cpu"] = &CgroupsCpushareIsolatorProcess::create;
-  creators["cgroups/mem"] = &CgroupsMemIsolatorProcess::create;
-#endif // __linux__
-
-  vector<Owned<Isolator> > isolators;
+  Try<MesosContainerizer*> containerizer =
+    MesosContainerizer::create(flags, local);
 
-  foreach (const string& type, strings::split(isolation, ",")) {
-    if (creators.contains(type)) {
-      Try<Isolator*> isolator = creators[type](flags);
-      if (isolator.isError()) {
-        return Error(
-            "Could not create isolator " + type + ": " + isolator.error());
-      } else {
-        isolators.push_back(Owned<Isolator>(isolator.get()));
-      }
-    } else {
-      return Error("Unknown or unsupported isolator: " + type);
-    }
-  }
-
-#ifdef __linux__
-  // Use cgroups on Linux if any cgroups isolators are used.
-  Try<Launcher*> launcher = strings::contains(isolation, "cgroups")
-    ? LinuxLauncher::create(flags) : PosixLauncher::create(flags);
-#else
-  Try<Launcher*> launcher = PosixLauncher::create(flags);
-#endif // __linux__
-  if (launcher.isError()) {
-    return Error("Failed to create launcher: " + launcher.error());
+  if (containerizer.isError()) {
+    return Error(containerizer.error());
   }
 
-  return new MesosContainerizer(
-      flags, local, Owned<Launcher>(launcher.get()), isolators);
+  return containerizer.get();
 }
 
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/10300962/src/slave/containerizer/mesos_containerizer.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos_containerizer.cpp b/src/slave/containerizer/mesos_containerizer.cpp
index 71b6108..2a4816e 100644
--- a/src/slave/containerizer/mesos_containerizer.cpp
+++ b/src/slave/containerizer/mesos_containerizer.cpp
@@ -31,8 +31,20 @@
 #include "slave/paths.hpp"
 #include "slave/slave.hpp"
 
+#ifdef __linux__
+#include "slave/containerizer/linux_launcher.hpp"
+#endif // __linux__
+#include "slave/containerizer/containerizer.hpp"
+#include "slave/containerizer/isolator.hpp"
+#include "slave/containerizer/launcher.hpp"
 #include "slave/containerizer/mesos_containerizer.hpp"
 
+#include "slave/containerizer/isolators/posix.hpp"
+#ifdef __linux__
+#include "slave/containerizer/isolators/cgroups/cpushare.hpp"
+#include "slave/containerizer/isolators/cgroups/mem.hpp"
+#endif // __linux__
+
 using std::list;
 using std::map;
 using std::string;
@@ -88,6 +100,71 @@ map<string, string> fetcherEnvironment(
 }
 
 
+Try<MesosContainerizer*> MesosContainerizer::create(
+    const Flags& flags,
+    bool local)
+{
+  string isolation;
+  if (flags.isolation == "process") {
+    LOG(WARNING) << "The 'process' isolation flag is deprecated, "
+                 << "please update your flags to"
+                 << " '--isolation=posix/cpu,posix/mem'.";
+    isolation = "posix/cpu,posix/mem";
+  } else if (flags.isolation == "cgroups") {
+    LOG(WARNING) << "The 'cgroups' isolation flag is deprecated, "
+                 << "please update your flags to"
+                 << " '--isolation=cgroups/cpu,cgroups/mem'.";
+    isolation = "cgroups/cpu,cgroups/mem";
+  } else {
+    isolation = flags.isolation;
+  }
+
+  LOG(INFO) << "Using isolation: " << isolation;
+
+  // Create a MesosContainerizerProcess using isolators and a launcher.
+  hashmap<std::string, Try<Isolator*> (*)(const Flags&)> creators;
+
+  creators["posix/cpu"]   = &PosixCpuIsolatorProcess::create;
+  creators["posix/mem"]   = &PosixMemIsolatorProcess::create;
+#ifdef __linux__
+  creators["cgroups/cpu"] = &CgroupsCpushareIsolatorProcess::create;
+  creators["cgroups/mem"] = &CgroupsMemIsolatorProcess::create;
+#endif // __linux__
+
+  vector<Owned<Isolator> > isolators;
+
+  foreach (const string& type, strings::split(isolation, ",")) {
+    if (creators.contains(type)) {
+      Try<Isolator*> isolator = creators[type](flags);
+      if (isolator.isError()) {
+        return Error(
+            "Could not create isolator " + type + ": " + isolator.error());
+      } else {
+        isolators.push_back(Owned<Isolator>(isolator.get()));
+      }
+    } else {
+      return Error("Unknown or unsupported isolator: " + type);
+    }
+  }
+
+#ifdef __linux__
+  // Use cgroups on Linux if any cgroups isolators are used.
+  Try<Launcher*> launcher = strings::contains(isolation, "cgroups")
+    ? LinuxLauncher::create(flags)
+    : PosixLauncher::create(flags);
+#else
+  Try<Launcher*> launcher = PosixLauncher::create(flags);
+#endif // __linux__
+
+  if (launcher.isError()) {
+    return Error("Failed to create launcher: " + launcher.error());
+  }
+
+  return new MesosContainerizer(
+      flags, local, Owned<Launcher>(launcher.get()), isolators);
+}
+
+
 MesosContainerizer::MesosContainerizer(
     const Flags& flags,
     bool local,

http://git-wip-us.apache.org/repos/asf/mesos/blob/10300962/src/slave/containerizer/mesos_containerizer.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos_containerizer.hpp b/src/slave/containerizer/mesos_containerizer.hpp
index 5353450..1f5908a 100644
--- a/src/slave/containerizer/mesos_containerizer.hpp
+++ b/src/slave/containerizer/mesos_containerizer.hpp
@@ -40,6 +40,8 @@ class MesosContainerizerProcess;
 class MesosContainerizer : public Containerizer
 {
 public:
+  static Try<MesosContainerizer*> create(const Flags& flags, bool local);
+
   MesosContainerizer(
       const Flags& flags,
       bool local,

http://git-wip-us.apache.org/repos/asf/mesos/blob/10300962/src/tests/containerizer_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/containerizer_tests.cpp b/src/tests/containerizer_tests.cpp
index 517859f..9d20853 100644
--- a/src/tests/containerizer_tests.cpp
+++ b/src/tests/containerizer_tests.cpp
@@ -299,7 +299,8 @@ public:
 
 
 // The isolator has a prepare command that succeeds.
-TEST_F(MesosContainerizerIsolatorPreparationTest, ScriptSucceeds) {
+TEST_F(MesosContainerizerIsolatorPreparationTest, ScriptSucceeds)
+{
   string directory = os::getcwd(); // We're inside a temporary sandbox.
   string file = path::join(directory, "child.script.executed");
 
@@ -342,7 +343,8 @@ TEST_F(MesosContainerizerIsolatorPreparationTest, ScriptSucceeds) {
 
 
 // The isolator has a prepare command that fails.
-TEST_F(MesosContainerizerIsolatorPreparationTest, ScriptFails) {
+TEST_F(MesosContainerizerIsolatorPreparationTest, ScriptFails)
+{
   string directory = os::getcwd(); // We're inside a temporary sandbox.
   string file = path::join(directory, "child.script.executed");
 
@@ -387,7 +389,8 @@ TEST_F(MesosContainerizerIsolatorPreparationTest, ScriptFails) {
 // There are two isolators, one with a prepare command that succeeds and
 // another that fails. The execution order is not defined but the launch should
 // fail from the failing prepare command.
-TEST_F(MesosContainerizerIsolatorPreparationTest, MultipleScripts) {
+TEST_F(MesosContainerizerIsolatorPreparationTest, MultipleScripts)
+{
   string directory = os::getcwd(); // We're inside a temporary sandbox.
   string file1 = path::join(directory, "child.script.executed.1");
   string file2 = path::join(directory, "child.script.executed.2");

http://git-wip-us.apache.org/repos/asf/mesos/blob/10300962/src/tests/slave_recovery_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/slave_recovery_tests.cpp b/src/tests/slave_recovery_tests.cpp
index 7e1c31e..85c57b2 100644
--- a/src/tests/slave_recovery_tests.cpp
+++ b/src/tests/slave_recovery_tests.cpp
@@ -126,11 +126,11 @@ public:
   }
 };
 
-// Note: Although these tests are typed it is Containerizer::create() that
-// decides which Containerizer to create based on the flags - see
-// SlaveRecoveryTest.
+
+// Containerizer types to run the tests.
 typedef ::testing::Types<slave::MesosContainerizer> ContainerizerTypes;
 
+
 TYPED_TEST_CASE(SlaveRecoveryTest, ContainerizerTypes);
 
 // Enable checkpointing on the slave and ensure recovery works.
@@ -141,7 +141,7 @@ TYPED_TEST(SlaveRecoveryTest, RecoverSlaveState)
 
   slave::Flags flags = this->CreateSlaveFlags();
 
-  Try<Containerizer*> containerizer = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer);
 
   Try<PID<Slave> > slave = this->StartSlave(containerizer.get(), flags);
@@ -320,7 +320,7 @@ TYPED_TEST(SlaveRecoveryTest, RecoverStatusUpdateManager)
 
   slave::Flags flags = this->CreateSlaveFlags();
 
-  Try<Containerizer*> containerizer1 = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer1 = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer1);
 
   Try<PID<Slave> > slave = this->StartSlave(containerizer1.get(), flags);
@@ -378,7 +378,7 @@ TYPED_TEST(SlaveRecoveryTest, RecoverStatusUpdateManager)
     .WillRepeatedly(Return());       // Ignore subsequent updates.
 
   // Restart the slave (use same flags) with a new containerizer.
-  Try<Containerizer*> containerizer2 = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer2 = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer2);
 
   slave = this->StartSlave(containerizer2.get(), flags);
@@ -405,7 +405,7 @@ TYPED_TEST(SlaveRecoveryTest, ReconnectExecutor)
 
   slave::Flags flags = this->CreateSlaveFlags();
 
-  Try<Containerizer*> containerizer1 = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer1 = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer1);
 
   Try<PID<Slave> > slave = this->StartSlave(containerizer1.get(), flags);
@@ -458,7 +458,7 @@ TYPED_TEST(SlaveRecoveryTest, ReconnectExecutor)
     .WillRepeatedly(Return());       // Ignore subsequent updates.
 
   // Restart the slave (use same flags) with a new containerizer.
-  Try<Containerizer*> containerizer2 = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer2 = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer2);
 
   slave = this->StartSlave(containerizer2.get(), flags);
@@ -499,7 +499,7 @@ TYPED_TEST(SlaveRecoveryTest, RecoverUnregisteredExecutor)
 
   slave::Flags flags = this->CreateSlaveFlags();
 
-  Try<Containerizer*> containerizer1 = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer1 = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer1);
 
   Try<PID<Slave> > slave = this->StartSlave(containerizer1.get(), flags);
@@ -551,7 +551,7 @@ TYPED_TEST(SlaveRecoveryTest, RecoverUnregisteredExecutor)
   Future<Nothing> _recover = FUTURE_DISPATCH(_, &Slave::_recover);
 
   // Restart the slave (use same flags) with a new containerizer.
-  Try<Containerizer*> containerizer2 = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer2 = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer2);
 
   Future<vector<Offer> > offers2;
@@ -609,7 +609,7 @@ TYPED_TEST(SlaveRecoveryTest, RecoverTerminatedExecutor)
 
   slave::Flags flags = this->CreateSlaveFlags();
 
-  Try<Containerizer*> containerizer1 = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer1 = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer1);
 
   Try<PID<Slave> > slave = this->StartSlave(containerizer1.get(), flags);
@@ -670,7 +670,7 @@ TYPED_TEST(SlaveRecoveryTest, RecoverTerminatedExecutor)
   Future<Nothing> _recover = FUTURE_DISPATCH(_, &Slave::_recover);
 
   // Restart the slave (use same flags) with a new containerizer.
-  Try<Containerizer*> containerizer2 = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer2 = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer2);
 
   Future<vector<Offer> > offers2;
@@ -734,7 +734,7 @@ TYPED_TEST(SlaveRecoveryTest, DISABLED_RecoveryTimeout)
   slave::Flags flags = this->CreateSlaveFlags();
   flags.recovery_timeout = Milliseconds(1);
 
-  Try<Containerizer*> containerizer1 = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer1 = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer1);
 
   Try<PID<Slave> > slave = this->StartSlave(containerizer1.get(), flags);
@@ -790,7 +790,7 @@ TYPED_TEST(SlaveRecoveryTest, DISABLED_RecoveryTimeout)
   Future<Nothing> _recover = FUTURE_DISPATCH(_, &Slave::_recover);
 
   // Restart the slave (use same flags) with a new containerizer.
-  Try<Containerizer*> containerizer2 = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer2 = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer2);
 
   slave = this->StartSlave(containerizer2.get(), flags);
@@ -828,7 +828,7 @@ TYPED_TEST(SlaveRecoveryTest, RecoverCompletedExecutor)
 
   slave::Flags flags = this->CreateSlaveFlags();
 
-  Try<Containerizer*> containerizer1 = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer1 = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer1);
 
   Try<PID<Slave> > slave = this->StartSlave(containerizer1.get(), flags);
@@ -881,7 +881,7 @@ TYPED_TEST(SlaveRecoveryTest, RecoverCompletedExecutor)
       _, &GarbageCollectorProcess::schedule);
 
   // Restart the slave (use same flags) with a new containerizer.
-  Try<Containerizer*> containerizer2 = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer2 = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer2);
 
   Future<vector<Offer> > offers2;
@@ -918,7 +918,7 @@ TYPED_TEST(SlaveRecoveryTest, CleanupExecutor)
 
   slave::Flags flags = this->CreateSlaveFlags();
 
-  Try<Containerizer*> containerizer1 = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer1 = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer1);
 
   Try<PID<Slave> > slave = this->StartSlave(containerizer1.get(), flags);
@@ -975,7 +975,7 @@ TYPED_TEST(SlaveRecoveryTest, CleanupExecutor)
   Future<Nothing> __recover = FUTURE_DISPATCH(_, &Slave::__recover);
 
   // Restart the slave in 'cleanup' recovery mode with a new isolator.
-  Try<Containerizer*> containerizer2 = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer2 = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer2);
 
   flags.recover = "cleanup";
@@ -1018,7 +1018,7 @@ TYPED_TEST(SlaveRecoveryTest, RemoveNonCheckpointingFramework)
 
   slave::Flags flags = this->CreateSlaveFlags();
 
-  Try<Containerizer*> containerizer = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer);
 
   Try<PID<Slave> > slave = this->StartSlave(containerizer.get(), flags);
@@ -1122,7 +1122,7 @@ TYPED_TEST(SlaveRecoveryTest, NonCheckpointingFramework)
 
   slave::Flags flags = this->CreateSlaveFlags();
 
-  Try<Containerizer*> containerizer = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer);
 
   Try<PID<Slave> > slave = this->StartSlave(containerizer.get(), flags);
@@ -1212,7 +1212,7 @@ TYPED_TEST(SlaveRecoveryTest, NonCheckpointingSlave)
   Future<RegisterSlaveMessage> registerSlaveMessage =
     FUTURE_PROTOBUF(RegisterSlaveMessage(), _, _);
 
-  Try<Containerizer*> containerizer = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer);
 
   Try<PID<Slave> > slave = this->StartSlave(containerizer.get(), flags);
@@ -1262,7 +1262,7 @@ TYPED_TEST(SlaveRecoveryTest, KillTask)
 
   slave::Flags flags = this->CreateSlaveFlags();
 
-  Try<Containerizer*> containerizer1 = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer1 = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer1);
 
   Try<PID<Slave> > slave = this->StartSlave(containerizer1.get(), flags);
@@ -1313,7 +1313,7 @@ TYPED_TEST(SlaveRecoveryTest, KillTask)
     FUTURE_PROTOBUF(ReregisterSlaveMessage(), _, _);
 
   // Restart the slave (use same flags) with a new isolator.
-  Try<Containerizer*> containerizer2 = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer2 = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer2);
 
   slave = this->StartSlave(containerizer2.get(), flags);
@@ -1379,7 +1379,7 @@ TYPED_TEST(SlaveRecoveryTest, Reboot)
   slave::Flags flags = this->CreateSlaveFlags();
   flags.strict = false;
 
-  Try<Containerizer*> containerizer1 = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer1 = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer1);
 
   Try<PID<Slave> > slave = this->StartSlave(containerizer1.get(), flags);
@@ -1450,7 +1450,7 @@ TYPED_TEST(SlaveRecoveryTest, Reboot)
     FUTURE_PROTOBUF(RegisterSlaveMessage(), _, _);
 
   // Restart the slave (use same flags) with a new containerizer.
-  Try<Containerizer*> containerizer2 = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer2 = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer2);
 
   Future<vector<Offer> > offers2;
@@ -1488,7 +1488,7 @@ TYPED_TEST(SlaveRecoveryTest, GCExecutor)
   slave::Flags flags = this->CreateSlaveFlags();
   flags.strict = false;
 
-  Try<Containerizer*> containerizer1 = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer1 = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer1);
 
   Try<PID<Slave> > slave = this->StartSlave(containerizer1.get(), flags);
@@ -1564,7 +1564,7 @@ TYPED_TEST(SlaveRecoveryTest, GCExecutor)
     FUTURE_PROTOBUF(ReregisterSlaveMessage(), _, _);
 
   // Restart the slave (use same flags) with a new isolator.
-  Try<Containerizer*> containerizer2 = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer2 = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer2);
 
   Future<vector<Offer> > offers2;
@@ -1630,7 +1630,7 @@ TYPED_TEST(SlaveRecoveryTest, ShutdownSlave)
 
   slave::Flags flags = this->CreateSlaveFlags();
 
-  Try<Containerizer*> containerizer1 = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer1 = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer1);
 
   Try<PID<Slave> > slave = this->StartSlave(containerizer1.get(), flags);
@@ -1712,7 +1712,7 @@ TYPED_TEST(SlaveRecoveryTest, ShutdownSlave)
     .WillRepeatedly(Return());        // Ignore subsequent offers.
 
   // Now restart the slave (use same flags) with a new containerizer.
-  Try<Containerizer*> containerizer2 = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer2 = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer2);
 
   slave = this->StartSlave(containerizer2.get(), flags);
@@ -1756,7 +1756,7 @@ TYPED_TEST(SlaveRecoveryTest, RegisterDisconnectedSlave)
 
   slave::Flags flags = this->CreateSlaveFlags();
 
-  Try<Containerizer*> containerizer = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer);
 
   Try<PID<Slave> > slave = this->StartSlave(containerizer.get(), flags);
@@ -1866,7 +1866,7 @@ TYPED_TEST(SlaveRecoveryTest, ReconcileKillTask)
 
   slave::Flags flags = this->CreateSlaveFlags();
 
-  Try<Containerizer*> containerizer1 = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer1 = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer1);
 
   Try<PID<Slave> > slave = this->StartSlave(containerizer1.get(), flags);
@@ -1925,7 +1925,7 @@ TYPED_TEST(SlaveRecoveryTest, ReconcileKillTask)
     .WillOnce(FutureArg<1>(&status));
 
   // Now restart the slave (use same flags) with a new containerizer.
-  Try<Containerizer*> containerizer2 = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer2 = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer2);
 
   Future<vector<Offer> > offers2;
@@ -1966,7 +1966,7 @@ TYPED_TEST(SlaveRecoveryTest, ReconcileShutdownFramework)
 
   slave::Flags flags = this->CreateSlaveFlags();
 
-  Try<Containerizer*> containerizer1 = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer1 = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer1);
 
   Try<PID<Slave> > slave = this->StartSlave(containerizer1.get(), flags);
@@ -2034,7 +2034,7 @@ TYPED_TEST(SlaveRecoveryTest, ReconcileShutdownFramework)
     FUTURE_DISPATCH(_, &Slave::executorTerminated);
 
   // Now restart the slave (use same flags) with a new containerizer.
-  Try<Containerizer*> containerizer2 = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer2 = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer2);
 
   slave = this->StartSlave(containerizer2.get(), flags);
@@ -2071,7 +2071,7 @@ TYPED_TEST(SlaveRecoveryTest, ReconcileTasksMissingFromSlave)
 
   EXPECT_CALL(allocator, slaveAdded(_, _, _));
 
-  Try<Containerizer*> containerizer1 = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer1 = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer1);
 
   Try<PID<Slave> > slave = this->StartSlave(containerizer1.get(), flags);
@@ -2175,7 +2175,7 @@ TYPED_TEST(SlaveRecoveryTest, ReconcileTasksMissingFromSlave)
     .WillRepeatedly(Return());        // Ignore subsequent offers.
 
   // Restart the slave (use same flags) with a new containerizer.
-  Try<Containerizer*> containerizer2 = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer2 = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer2);
 
   slave = this->StartSlave(containerizer2.get(), flags);
@@ -2235,7 +2235,7 @@ TYPED_TEST(SlaveRecoveryTest, SchedulerFailover)
 
   slave::Flags flags = this->CreateSlaveFlags();
 
-  Try<Containerizer*> containerizer1 = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer1 = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer1);
 
   Try<PID<Slave> > slave = this->StartSlave(containerizer1.get(), flags);
@@ -2314,7 +2314,7 @@ TYPED_TEST(SlaveRecoveryTest, SchedulerFailover)
       FUTURE_PROTOBUF(ReregisterSlaveMessage(), _, _);
 
   // Restart the slave (use same flags) with a new containerizer.
-  Try<Containerizer*> containerizer2 = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer2 = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer2);
 
   slave = this->StartSlave(containerizer2.get(), flags);
@@ -2393,7 +2393,7 @@ TYPED_TEST(SlaveRecoveryTest, PartitionedSlave)
 
   slave::Flags flags = this->CreateSlaveFlags();
 
-  Try<Containerizer*> containerizer1 = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer1 = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer1);
 
   Try<PID<Slave> > slave = this->StartSlave(containerizer1.get(), flags);
@@ -2494,7 +2494,7 @@ TYPED_TEST(SlaveRecoveryTest, PartitionedSlave)
     FUTURE_PROTOBUF(RegisterSlaveMessage(), _, _);
 
   // Restart the slave (use same flags) with a new isolator.
-  Try<Containerizer*> containerizer2 = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer2 = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer2);
 
   slave = this->StartSlave(containerizer2.get(), flags);
@@ -2523,7 +2523,7 @@ TYPED_TEST(SlaveRecoveryTest, MasterFailover)
 
   slave::Flags flags = this->CreateSlaveFlags();
 
-  Try<Containerizer*> containerizer1 = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer1 = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer1);
 
   Try<PID<Slave> > slave = this->StartSlave(containerizer1.get(), flags);
@@ -2597,7 +2597,7 @@ TYPED_TEST(SlaveRecoveryTest, MasterFailover)
     FUTURE_PROTOBUF(ReregisterSlaveMessage(), _, _);
 
   // Restart the slave (use same flags) with a new isolator.
-  Try<Containerizer*> containerizer2 = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer2 = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer2);
 
   slave = this->StartSlave(containerizer2.get(), flags);
@@ -2664,7 +2664,7 @@ TYPED_TEST(SlaveRecoveryTest, MultipleFrameworks)
 
   slave::Flags flags = this->CreateSlaveFlags();
 
-  Try<Containerizer*> containerizer1 = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer1 = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer1);
 
   Try<PID<Slave> > slave = this->StartSlave(containerizer1.get(), flags);
@@ -2761,7 +2761,7 @@ TYPED_TEST(SlaveRecoveryTest, MultipleFrameworks)
     FUTURE_PROTOBUF(ReregisterSlaveMessage(), _, _);
 
   // Restart the slave (use same flags) with a new containerizer.
-  Try<Containerizer*> containerizer2 = Containerizer::create(flags, true);
+  Try<TypeParam*> containerizer2 = TypeParam::create(flags, true);
   ASSERT_SOME(containerizer2);
 
   slave = this->StartSlave(containerizer2.get(), flags);
@@ -2856,7 +2856,7 @@ TYPED_TEST(SlaveRecoveryTest, MultipleSlaves)
   // Disable putting slave into cgroup(s) because this is a multi-slave test.
   flags1.slave_subsystems = None();
 #endif // __linux
-  Try<Containerizer*> containerizer1 = Containerizer::create(flags1, true);
+  Try<TypeParam*> containerizer1 = TypeParam::create(flags1, true);
   ASSERT_SOME(containerizer1);
 
   Try<PID<Slave> > slave1 = this->StartSlave(containerizer1.get(), flags1);
@@ -2891,7 +2891,7 @@ TYPED_TEST(SlaveRecoveryTest, MultipleSlaves)
   // Disable putting slave into cgroup(s) because this is a multi-slave test.
   flags2.slave_subsystems = "";
 #endif // __linux
-  Try<Containerizer*> containerizer2 = Containerizer::create(flags2, true);
+  Try<TypeParam*> containerizer2 = TypeParam::create(flags2, true);
   ASSERT_SOME(containerizer2);
 
   Try<PID<Slave> > slave2 = this->StartSlave(containerizer2.get(), flags2);
@@ -2930,13 +2930,13 @@ TYPED_TEST(SlaveRecoveryTest, MultipleSlaves)
     FUTURE_PROTOBUF(ReregisterSlaveMessage(), _, _);
 
   // Restart both slaves using the same flags with new containerizers.
-  Try<Containerizer*> containerizer3 = Containerizer::create(flags1, true);
+  Try<TypeParam*> containerizer3 = TypeParam::create(flags1, true);
   ASSERT_SOME(containerizer3);
 
   slave1 = this->StartSlave(containerizer3.get(), flags1);
   ASSERT_SOME(slave1);
 
-  Try<Containerizer*> containerizer4 = Containerizer::create(flags2, true);
+  Try<TypeParam*> containerizer4 = TypeParam::create(flags2, true);
   ASSERT_SOME(containerizer4);
 
   slave2 = this->StartSlave(containerizer4.get(), flags2);
@@ -2999,17 +2999,20 @@ TYPED_TEST(SlaveRecoveryTest, MultipleSlaves)
 }
 
 
-TYPED_TEST(SlaveRecoveryTest, ResourceStatistics)
+// The slave is stopped after it dispatched Containerizer::launch but
+// before the containerizer has processed the launch. When the slave
+// comes back up it should send a TASK_FAILED for the task.
+// NOTE: This is a 'TYPED_TEST' but we don't use 'TypeParam'.
+TYPED_TEST(SlaveRecoveryTest, RestartBeforeContainerizerLaunch)
 {
   Try<PID<Master> > master = this->StartMaster();
   ASSERT_SOME(master);
 
   slave::Flags flags = this->CreateSlaveFlags();
 
-  Try<Containerizer*> containerizer1 = Containerizer::create(flags, true);
-  ASSERT_SOME(containerizer1);
+  TestContainerizer* containerizer1 = new TestContainerizer();
 
-  Try<PID<Slave> > slave = this->StartSlave(containerizer1.get(), flags);
+  Try<PID<Slave> > slave = this->StartSlave(containerizer1, flags);
   ASSERT_SOME(slave);
 
   MockScheduler sched;
@@ -3038,76 +3041,69 @@ TYPED_TEST(SlaveRecoveryTest, ResourceStatistics)
   vector<TaskInfo> tasks;
   tasks.push_back(task); // Long-running task.
 
-  // Message expectations.
-  Future<Message> registerExecutor =
-    FUTURE_MESSAGE(Eq(RegisterExecutorMessage().GetTypeName()), _, _);
+  // Expect the launch but don't do anything.
+  Future<Nothing> launch;
+  EXPECT_CALL(*containerizer1, launch(_, _, _, _, _, _, _))
+    .WillOnce(DoAll(FutureSatisfy(&launch),
+                    Return(Future<Nothing>())));
 
   driver.launchTasks(offers.get()[0].id(), tasks);
 
-  AWAIT_READY(registerExecutor);
+  // Once we get the launch restart the slave.
+  AWAIT_READY(launch);
 
   this->Stop(slave.get());
-  delete containerizer1.get();
-
-  // Set up so we can wait until the new slave updates the container's
-  // resources (this occurs after the executor has re-registered).
-  // TODO(idownes): This assumes the containerizer is a MesosContainerizer.
-  Future<Nothing> update =
-    FUTURE_DISPATCH(_, &MesosContainerizerProcess::update);
-
-  // Restart the slave (use same flags) with a new containerizer.
-  Try<Containerizer*> containerizer2 = Containerizer::create(flags, true);
-  ASSERT_SOME(containerizer2);
+  delete containerizer1;
 
-  slave = this->StartSlave(containerizer2.get(), flags);
-  ASSERT_SOME(slave);
+  Future<TaskStatus> status;
+  EXPECT_CALL(sched, statusUpdate(_, _))
+    .WillOnce(FutureArg<1>(&status));
 
-  // Wait until the containerizer is updated.
-  AWAIT_READY(update);
+  Future<Nothing> _recover = FUTURE_DISPATCH(_, &Slave::_recover);
 
-  Future<hashset<ContainerID> > containers = containerizer2.get()->containers();
-  AWAIT_READY(containers);
-  ASSERT_EQ(1u, containers.get().size());
+  TestContainerizer* containerizer2 = new TestContainerizer();
 
-  ContainerID containerId = *(containers.get().begin());
+  slave = this->StartSlave(containerizer2, flags);
+  ASSERT_SOME(slave);
 
-  Future<ResourceStatistics> usage = containerizer2.get()->usage(containerId);
-  AWAIT_READY(usage);
+  Clock::pause();
 
-  // Check the resource limits are set.
-  EXPECT_TRUE(usage.get().has_cpus_limit());
-  EXPECT_TRUE(usage.get().has_mem_limit_bytes());
+  AWAIT_READY(_recover);
 
-  Future<containerizer::Termination> wait =
-    containerizer2.get()->wait(containerId);
+  Clock::settle(); // Wait for slave to schedule reregister timeout.
 
-  containerizer2.get()->destroy(containerId);
+  Clock::advance(EXECUTOR_REREGISTER_TIMEOUT);
 
-  AWAIT_READY(wait);
+  // Scheduler should receive the TASK_FAILED update.
+  AWAIT_READY(status);
+  ASSERT_EQ(TASK_FAILED, status.get().state());
 
   driver.stop();
   driver.join();
 
   this->Shutdown();
-
-  delete containerizer2.get();
+  delete containerizer2;
 }
 
 
-// The slave is stopped after it dispatched Containerizer::launch but
-// before the containerizer has processed the launch. When the slave
-// comes back up it should send a TASK_FAILED for the task.
-// NOTE: This is a 'TYPED_TEST' but we don't use 'TypeParam'.
-TYPED_TEST(SlaveRecoveryTest, RestartBeforeContainerizerLaunch)
+// We explicitly instantiate a SlaveRecoveryTest for test cases where
+// we assume we'll only have the MesosContainerizer.
+class MesosContainerizerSlaveRecoveryTest
+  : public SlaveRecoveryTest<MesosContainerizer> {};
+
+
+TEST_F(MesosContainerizerSlaveRecoveryTest, ResourceStatistics)
 {
   Try<PID<Master> > master = this->StartMaster();
   ASSERT_SOME(master);
 
   slave::Flags flags = this->CreateSlaveFlags();
 
-  TestContainerizer* containerizer1 = new TestContainerizer();
+  Try<MesosContainerizer*> containerizer1 =
+    MesosContainerizer::create(flags, true);
+  ASSERT_SOME(containerizer1);
 
-  Try<PID<Slave> > slave = this->StartSlave(containerizer1, flags);
+  Try<PID<Slave> > slave = this->StartSlave(containerizer1.get(), flags);
   ASSERT_SOME(slave);
 
   MockScheduler sched;
@@ -3136,46 +3132,57 @@ TYPED_TEST(SlaveRecoveryTest, RestartBeforeContainerizerLaunch)
   vector<TaskInfo> tasks;
   tasks.push_back(task); // Long-running task.
 
-  // Expect the launch but don't do anything.
-  Future<Nothing> launch;
-  EXPECT_CALL(*containerizer1, launch(_, _, _, _, _, _, _))
-    .WillOnce(DoAll(FutureSatisfy(&launch),
-                    Return(Future<Nothing>())));
+  // Message expectations.
+  Future<Message> registerExecutor =
+    FUTURE_MESSAGE(Eq(RegisterExecutorMessage().GetTypeName()), _, _);
 
   driver.launchTasks(offers.get()[0].id(), tasks);
 
-  // Once we get the launch restart the slave.
-  AWAIT_READY(launch);
+  AWAIT_READY(registerExecutor);
 
   this->Stop(slave.get());
-  delete containerizer1;
-
-  Future<TaskStatus> status;
-  EXPECT_CALL(sched, statusUpdate(_, _))
-    .WillOnce(FutureArg<1>(&status));
+  delete containerizer1.get();
 
-  Future<Nothing> _recover = FUTURE_DISPATCH(_, &Slave::_recover);
+  // Set up so we can wait until the new slave updates the container's
+  // resources (this occurs after the executor has re-registered).
+  Future<Nothing> update =
+    FUTURE_DISPATCH(_, &MesosContainerizerProcess::update);
 
-  TestContainerizer* containerizer2 = new TestContainerizer();
+  // Restart the slave (use same flags) with a new containerizer.
+  Try<MesosContainerizer*> containerizer2 =
+    MesosContainerizer::create(flags, true);
+  ASSERT_SOME(containerizer2);
 
-  slave = this->StartSlave(containerizer2, flags);
+  slave = this->StartSlave(containerizer2.get(), flags);
   ASSERT_SOME(slave);
 
-  Clock::pause();
+  // Wait until the containerizer is updated.
+  AWAIT_READY(update);
 
-  AWAIT_READY(_recover);
+  Future<hashset<ContainerID> > containers = containerizer2.get()->containers();
+  AWAIT_READY(containers);
+  ASSERT_EQ(1u, containers.get().size());
 
-  Clock::settle(); // Wait for slave to schedule reregister timeout.
+  ContainerID containerId = *(containers.get().begin());
 
-  Clock::advance(EXECUTOR_REREGISTER_TIMEOUT);
+  Future<ResourceStatistics> usage = containerizer2.get()->usage(containerId);
+  AWAIT_READY(usage);
 
-  // Scheduler should receive the TASK_FAILED update.
-  AWAIT_READY(status);
-  ASSERT_EQ(TASK_FAILED, status.get().state());
+  // Check the resource limits are set.
+  EXPECT_TRUE(usage.get().has_cpus_limit());
+  EXPECT_TRUE(usage.get().has_mem_limit_bytes());
+
+  Future<containerizer::Termination> wait =
+    containerizer2.get()->wait(containerId);
+
+  containerizer2.get()->destroy(containerId);
+
+  AWAIT_READY(wait);
 
   driver.stop();
   driver.join();
 
   this->Shutdown();
-  delete containerizer2;
+
+  delete containerizer2.get();
 }

http://git-wip-us.apache.org/repos/asf/mesos/blob/10300962/src/tests/slave_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/slave_tests.cpp b/src/tests/slave_tests.cpp
index 07ce882..0982455 100644
--- a/src/tests/slave_tests.cpp
+++ b/src/tests/slave_tests.cpp
@@ -57,6 +57,7 @@ using mesos::internal::master::Master;
 using mesos::internal::slave::GarbageCollectorProcess;
 using mesos::internal::slave::Slave;
 using mesos::internal::slave::Containerizer;
+using mesos::internal::slave::MesosContainerizer;
 using mesos::internal::slave::MesosContainerizerProcess;
 
 using process::Clock;
@@ -90,7 +91,8 @@ TEST_F(SlaveTest, ShutdownUnregisteredExecutor)
   // Set the isolation flag so we know a MesoContainerizer will be created.
   flags.isolation = "posix/cpu,posix/mem";
 
-  Try<Containerizer*> containerizer = Containerizer::create(flags, false);
+  Try<MesosContainerizer*> containerizer =
+    MesosContainerizer::create(flags, false);
   CHECK_SOME(containerizer);
 
   Try<PID<Slave> > slave = StartSlave(containerizer.get());