Repository: mesos
Updated Branches:
  refs/heads/master a640eb25a -> 3f6faa499


Exposed unknown container case from Containerizer::wait.

This allows the caller to distinguish between a failure and waiting
on an unknown container. This is important for the upcoming agent
child container API, as the end-user would benefit from the
distinction.

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


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

Branch: refs/heads/master
Commit: 3f6faa499c06ac608e02355cf0e72386a1477d46
Parents: a640eb2
Author: Benjamin Mahler <bmah...@apache.org>
Authored: Fri Sep 16 18:14:11 2016 -0700
Committer: Benjamin Mahler <bmah...@apache.org>
Committed: Wed Sep 21 15:02:04 2016 -0700

----------------------------------------------------------------------
 src/slave/containerizer/composing.cpp           |   8 +-
 src/slave/containerizer/composing.hpp           |   2 +-
 src/slave/containerizer/containerizer.hpp       |   3 +-
 src/slave/containerizer/docker.cpp              |   9 +-
 src/slave/containerizer/docker.hpp              |   4 +-
 src/slave/containerizer/mesos/containerizer.cpp |  14 +--
 src/slave/containerizer/mesos/containerizer.hpp |   4 +-
 src/slave/slave.cpp                             |  34 +++--
 src/slave/slave.hpp                             |   6 +-
 src/tests/cluster.cpp                           |   2 +-
 src/tests/containerizer.cpp                     |  10 +-
 src/tests/containerizer.hpp                     |   7 +-
 .../composing_containerizer_tests.cpp           |  26 +++-
 .../docker_containerizer_tests.cpp              |  64 ++++++++--
 .../containerizer/filesystem_isolator_tests.cpp | 125 ++++++++++++-------
 src/tests/containerizer/isolator_tests.cpp      |   7 +-
 .../containerizer/mesos_containerizer_tests.cpp | 105 ++++++++++++----
 src/tests/containerizer/port_mapping_tests.cpp  |   5 +-
 src/tests/health_check_tests.cpp                |   6 +-
 src/tests/hook_tests.cpp                        |  15 ++-
 src/tests/slave_recovery_tests.cpp              |  22 +++-
 21 files changed, 339 insertions(+), 139 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/3f6faa49/src/slave/containerizer/composing.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/composing.cpp 
b/src/slave/containerizer/composing.cpp
index 5ff3e65..9181309 100644
--- a/src/slave/containerizer/composing.cpp
+++ b/src/slave/containerizer/composing.cpp
@@ -80,7 +80,7 @@ public:
   Future<ContainerStatus> status(
       const ContainerID& containerId);
 
-  Future<ContainerTermination> wait(
+  Future<Option<ContainerTermination>> wait(
       const ContainerID& containerId);
 
   void destroy(const ContainerID& containerId);
@@ -206,7 +206,7 @@ Future<ContainerStatus> ComposingContainerizer::status(
 }
 
 
-Future<ContainerTermination> ComposingContainerizer::wait(
+Future<Option<ContainerTermination>> ComposingContainerizer::wait(
     const ContainerID& containerId)
 {
   return dispatch(process, &ComposingContainerizerProcess::wait, containerId);
@@ -436,11 +436,11 @@ Future<ContainerStatus> 
ComposingContainerizerProcess::status(
 }
 
 
-Future<ContainerTermination> ComposingContainerizerProcess::wait(
+Future<Option<ContainerTermination>> ComposingContainerizerProcess::wait(
     const ContainerID& containerId)
 {
   if (!containers_.contains(containerId)) {
-    return Failure("Container '" + containerId.value() + "' not found");
+    return None();
   }
 
   return containers_[containerId]->containerizer->wait(containerId);

http://git-wip-us.apache.org/repos/asf/mesos/blob/3f6faa49/src/slave/containerizer/composing.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/composing.hpp 
b/src/slave/containerizer/composing.hpp
index ef3c2ee..3df7604 100644
--- a/src/slave/containerizer/composing.hpp
+++ b/src/slave/containerizer/composing.hpp
@@ -72,7 +72,7 @@ public:
   virtual process::Future<ContainerStatus> status(
       const ContainerID& containerId);
 
-  virtual process::Future<mesos::slave::ContainerTermination> wait(
+  virtual process::Future<Option<mesos::slave::ContainerTermination>> wait(
       const ContainerID& containerId);
 
   virtual void destroy(const ContainerID& containerId);

http://git-wip-us.apache.org/repos/asf/mesos/blob/3f6faa49/src/slave/containerizer/containerizer.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/containerizer.hpp 
b/src/slave/containerizer/containerizer.hpp
index f13669d..5ee1107 100644
--- a/src/slave/containerizer/containerizer.hpp
+++ b/src/slave/containerizer/containerizer.hpp
@@ -122,9 +122,10 @@ public:
 
   // Wait on the 'ContainerTermination'. If the executor terminates,
   // the containerizer should also destroy the containerized context.
+  // Returns None if the container cannot be found.
   // The future may be failed if an error occurs during termination of
   // the executor or destruction of the container.
-  virtual process::Future<mesos::slave::ContainerTermination> wait(
+  virtual process::Future<Option<mesos::slave::ContainerTermination>> wait(
       const ContainerID& containerId) = 0;
 
   // Destroy a running container, killing all processes and releasing

http://git-wip-us.apache.org/repos/asf/mesos/blob/3f6faa49/src/slave/containerizer/docker.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/docker.cpp 
b/src/slave/containerizer/docker.cpp
index 26a7e7c..2e02943 100644
--- a/src/slave/containerizer/docker.cpp
+++ b/src/slave/containerizer/docker.cpp
@@ -714,7 +714,7 @@ Future<ResourceStatistics> DockerContainerizer::usage(
 }
 
 
-Future<ContainerTermination> DockerContainerizer::wait(
+Future<Option<ContainerTermination>> DockerContainerizer::wait(
     const ContainerID& containerId)
 {
   return dispatch(
@@ -1780,16 +1780,17 @@ Try<ResourceStatistics> 
DockerContainerizerProcess::cgroupsStatistics(
 }
 
 
-Future<ContainerTermination> DockerContainerizerProcess::wait(
+Future<Option<ContainerTermination>> DockerContainerizerProcess::wait(
     const ContainerID& containerId)
 {
   CHECK(!containerId.has_parent());
 
   if (!containers_.contains(containerId)) {
-    return Failure("Unknown container: " + stringify(containerId));
+    return None();
   }
 
-  return containers_[containerId]->termination.future();
+  return containers_.at(containerId)->termination.future()
+    .then(Option<ContainerTermination>::some);
 }
 
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/3f6faa49/src/slave/containerizer/docker.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/docker.hpp 
b/src/slave/containerizer/docker.hpp
index a378fa9..aa6a9d6 100644
--- a/src/slave/containerizer/docker.hpp
+++ b/src/slave/containerizer/docker.hpp
@@ -100,7 +100,7 @@ public:
   virtual process::Future<ResourceStatistics> usage(
       const ContainerID& containerId);
 
-  virtual process::Future<mesos::slave::ContainerTermination> wait(
+  virtual process::Future<Option<mesos::slave::ContainerTermination>> wait(
       const ContainerID& containerId);
 
   virtual void destroy(const ContainerID& containerId);
@@ -150,7 +150,7 @@ public:
   virtual process::Future<ResourceStatistics> usage(
       const ContainerID& containerId);
 
-  virtual process::Future<mesos::slave::ContainerTermination> wait(
+  virtual process::Future<Option<mesos::slave::ContainerTermination>> wait(
       const ContainerID& containerId);
 
   virtual void destroy(

http://git-wip-us.apache.org/repos/asf/mesos/blob/3f6faa49/src/slave/containerizer/mesos/containerizer.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/containerizer.cpp 
b/src/slave/containerizer/mesos/containerizer.cpp
index e54169b..01acd70 100644
--- a/src/slave/containerizer/mesos/containerizer.cpp
+++ b/src/slave/containerizer/mesos/containerizer.cpp
@@ -538,7 +538,7 @@ Future<ContainerStatus> MesosContainerizer::status(
 }
 
 
-Future<ContainerTermination> MesosContainerizer::wait(
+Future<Option<ContainerTermination>> MesosContainerizer::wait(
     const ContainerID& containerId)
 {
   return dispatch(process.get(),
@@ -1398,19 +1398,19 @@ Future<Nothing> MesosContainerizerProcess::launch(
 }
 
 
-Future<ContainerTermination> MesosContainerizerProcess::wait(
+Future<Option<ContainerTermination>> MesosContainerizerProcess::wait(
     const ContainerID& containerId)
 {
   CHECK(!containerId.has_parent());
 
   if (!containers_.contains(containerId)) {
-    // See the comments in destroy() for race conditions which lead
-    // to "unknown containers".
-    return Failure("Unknown container (could have already been destroyed): " +
-                   stringify(containerId));
+    // See the comments in destroy() for race conditions
+    // which lead to "unknown containers".
+    return None();
   }
 
-  return containers_[containerId]->promise.future();
+  return containers_.at(containerId)->promise.future()
+    .then(Option<ContainerTermination>::some);
 }
 
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/3f6faa49/src/slave/containerizer/mesos/containerizer.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/containerizer.hpp 
b/src/slave/containerizer/mesos/containerizer.hpp
index 078ef4f..a29da73 100644
--- a/src/slave/containerizer/mesos/containerizer.hpp
+++ b/src/slave/containerizer/mesos/containerizer.hpp
@@ -101,7 +101,7 @@ public:
   virtual process::Future<ContainerStatus> status(
       const ContainerID& containerId);
 
-  virtual process::Future<mesos::slave::ContainerTermination> wait(
+  virtual process::Future<Option<mesos::slave::ContainerTermination>> wait(
       const ContainerID& containerId);
 
   virtual void destroy(const ContainerID& containerId);
@@ -165,7 +165,7 @@ public:
   virtual process::Future<ContainerStatus> status(
       const ContainerID& containerId);
 
-  virtual process::Future<mesos::slave::ContainerTermination> wait(
+  virtual process::Future<Option<mesos::slave::ContainerTermination>> wait(
       const ContainerID& containerId);
 
   virtual process::Future<bool> exec(

http://git-wip-us.apache.org/repos/asf/mesos/blob/3f6faa49/src/slave/slave.cpp
----------------------------------------------------------------------
diff --git a/src/slave/slave.cpp b/src/slave/slave.cpp
index 7a9a541a..11e9c8a 100644
--- a/src/slave/slave.cpp
+++ b/src/slave/slave.cpp
@@ -4465,7 +4465,7 @@ void Slave::executorLaunched(
 void Slave::executorTerminated(
     const FrameworkID& frameworkId,
     const ExecutorID& executorId,
-    const Future<ContainerTermination>& termination)
+    const Future<Option<ContainerTermination>>& termination)
 {
   int status;
   // A termination failure indicates the containerizer could not destroy a
@@ -4481,14 +4481,20 @@ void Slave::executorTerminated(
                    : "discarded");
     // Set a special status for failure.
     status = -1;
-  } else if (!termination.get().has_status()) {
+  } else if (termination->isNone()) {
+    LOG(ERROR) << "Termination of executor '" << executorId
+               << "' of framework " << frameworkId
+               << " failed: unknown container";
+    // Set a special status for failure.
+    status = -1;
+  } else if (!termination->get().has_status()) {
     LOG(INFO) << "Executor '" << executorId
               << "' of framework " << frameworkId
               << " has terminated with unknown status";
     // Set a special status for None.
     status = -1;
   } else {
-    status = termination.get().status();
+    status = termination->get().status();
     LOG(INFO) << "Executor '" << executorId
               << "' of framework " << frameworkId << " "
               << WSTRINGIFY(status);
@@ -5855,7 +5861,7 @@ Future<bool> Slave::authorizeSandboxAccess(
 
 void Slave::sendExecutorTerminatedStatusUpdate(
     const TaskID& taskId,
-    const Future<ContainerTermination>& termination,
+    const Future<Option<ContainerTermination>>& termination,
     const FrameworkID& frameworkId,
     const Executor* executor)
 {
@@ -5866,8 +5872,9 @@ void Slave::sendExecutorTerminatedStatusUpdate(
   string message;
 
   // Determine the task state for the status update.
-  if (termination.isReady() && termination->has_state()) {
-    state = termination->state();
+  if (termination.isReady() &&
+      termination->isSome() && termination->get().has_state()) {
+    state = termination->get().state();
   } else if (executor->pendingTermination.isSome() &&
              executor->pendingTermination->has_state()) {
     state = executor->pendingTermination->state();
@@ -5877,8 +5884,9 @@ void Slave::sendExecutorTerminatedStatusUpdate(
 
   // Determine the task reason for the status update.
   // TODO(jieyu): Handle multiple reasons (MESOS-2657).
-  if (termination.isReady() && termination->reasons().size() > 0) {
-    reason = termination->reasons(0);
+  if (termination.isReady() &&
+      termination->isSome() && termination->get().reasons().size() > 0) {
+    reason = termination->get().reasons(0);
   } else if (executor->pendingTermination.isSome() &&
              executor->pendingTermination->reasons().size() > 0) {
     reason = executor->pendingTermination->reasons(0);
@@ -5895,9 +5903,13 @@ void Slave::sendExecutorTerminatedStatusUpdate(
   }
 
   if (!termination.isReady()) {
-    messages.push_back("Abnormal executor termination");
-  } else if (termination->has_message()) {
-    messages.push_back(termination->message());
+    messages.push_back(
+        "Abnormal executor termination: " +
+        (termination.isFailed() ? termination.failure() : "discarded future"));
+  } else if (termination->isNone()) {
+    messages.push_back("Abnormal executor termination: unknown container");
+  } else if (termination->get().has_message()) {
+    messages.push_back(termination->get().message());
   }
 
   if (messages.empty()) {

http://git-wip-us.apache.org/repos/asf/mesos/blob/3f6faa49/src/slave/slave.hpp
----------------------------------------------------------------------
diff --git a/src/slave/slave.hpp b/src/slave/slave.hpp
index 02d2eca..20ca2fb 100644
--- a/src/slave/slave.hpp
+++ b/src/slave/slave.hpp
@@ -290,7 +290,8 @@ public:
   void executorTerminated(
       const FrameworkID& frameworkId,
       const ExecutorID& executorId,
-      const process::Future<mesos::slave::ContainerTermination>& termination);
+      const process::Future<Option<
+          mesos::slave::ContainerTermination>>& termination);
 
   // NOTE: Pulled these to public to make it visible for testing.
   // TODO(vinod): Make tests friends to this class instead.
@@ -650,7 +651,8 @@ private:
 
   void sendExecutorTerminatedStatusUpdate(
       const TaskID& taskId,
-      const Future<mesos::slave::ContainerTermination>& termination,
+      const process::Future<Option<
+          mesos::slave::ContainerTermination>>& termination,
       const FrameworkID& frameworkId,
       const Executor* executor);
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/3f6faa49/src/tests/cluster.cpp
----------------------------------------------------------------------
diff --git a/src/tests/cluster.cpp b/src/tests/cluster.cpp
index f201b49..6a9d94b 100644
--- a/src/tests/cluster.cpp
+++ b/src/tests/cluster.cpp
@@ -551,7 +551,7 @@ Slave::~Slave()
     AWAIT_READY(containers);
 
     foreach (const ContainerID& containerId, containers.get()) {
-      process::Future<ContainerTermination> wait =
+      process::Future<Option<ContainerTermination>> wait =
         containerizer->wait(containerId);
 
       containerizer->destroy(containerId);

http://git-wip-us.apache.org/repos/asf/mesos/blob/3f6faa49/src/tests/containerizer.cpp
----------------------------------------------------------------------
diff --git a/src/tests/containerizer.cpp b/src/tests/containerizer.cpp
index bda3e6f..78e18e8 100644
--- a/src/tests/containerizer.cpp
+++ b/src/tests/containerizer.cpp
@@ -194,16 +194,17 @@ Future<bool> TestContainerizer::_launch(
 }
 
 
-Future<ContainerTermination> TestContainerizer::_wait(
-    const ContainerID& containerId)
+Future<Option<ContainerTermination>> TestContainerizer::_wait(
+    const ContainerID& containerId) const
 {
   // An unknown container is possible for tests where we "drop" the
   // 'launch' in order to verify recovery still works correctly.
   if (!promises.contains(containerId)) {
-    return Failure("Unknown container: " + stringify(containerId));
+    return None();
   }
 
-  return promises[containerId]->future();
+  return promises.at(containerId)->future()
+    .then(Option<ContainerTermination>::some);
 }
 
 
@@ -217,6 +218,7 @@ void TestContainerizer::destroy(
                  << executorId << "' of framework " << frameworkId;
     return;
   }
+
   _destroy(containers_[key]);
 }
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/3f6faa49/src/tests/containerizer.hpp
----------------------------------------------------------------------
diff --git a/src/tests/containerizer.hpp b/src/tests/containerizer.hpp
index f1fd579..8f69972 100644
--- a/src/tests/containerizer.hpp
+++ b/src/tests/containerizer.hpp
@@ -103,7 +103,8 @@ public:
 
   MOCK_METHOD1(
       wait,
-      process::Future<mesos::slave::ContainerTermination>(const ContainerID&));
+      process::Future<Option<mesos::slave::ContainerTermination>>(
+          const ContainerID&));
 
   MOCK_METHOD1(
       destroy,
@@ -127,8 +128,8 @@ private:
       const std::map<std::string, std::string>& environment,
       bool checkpoint);
 
-  process::Future<mesos::slave::ContainerTermination> _wait(
-      const ContainerID& containerId);
+  process::Future<Option<mesos::slave::ContainerTermination>> _wait(
+      const ContainerID& containerId) const;
 
   void _destroy(const ContainerID& containerID);
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/3f6faa49/src/tests/containerizer/composing_containerizer_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/containerizer/composing_containerizer_tests.cpp 
b/src/tests/containerizer/composing_containerizer_tests.cpp
index 51aab33..19e31b1 100644
--- a/src/tests/containerizer/composing_containerizer_tests.cpp
+++ b/src/tests/containerizer/composing_containerizer_tests.cpp
@@ -83,7 +83,7 @@ public:
 
   MOCK_METHOD1(
       wait,
-      process::Future<ContainerTermination>(
+      process::Future<Option<ContainerTermination>>(
           const ContainerID&));
 
   MOCK_METHOD1(
@@ -156,6 +156,30 @@ TEST_F(ComposingContainerizerTest, DestroyWhileLaunching)
   AWAIT_FAILED(launch);
 }
 
+
+// Ensures the containerizer responds correctly (returns None)
+// to a request to wait on an unknown container.
+TEST_F(ComposingContainerizerTest, WaitUnknownContainer)
+{
+  vector<Containerizer*> containerizers;
+
+  MockContainerizer* mockContainerizer = new MockContainerizer();
+  MockContainerizer* mockContainerizer2 = new MockContainerizer();
+
+  containerizers.push_back(mockContainerizer);
+  containerizers.push_back(mockContainerizer2);
+
+  ComposingContainerizer containerizer(containerizers);
+
+  ContainerID containerId;
+  containerId.set_value(UUID::random().toString());
+
+  Future<Option<ContainerTermination>> wait = containerizer.wait(containerId);
+
+  AWAIT_READY(wait);
+  EXPECT_NONE(wait.get());
+}
+
 } // namespace tests {
 } // namespace internal {
 } // namespace mesos {

http://git-wip-us.apache.org/repos/asf/mesos/blob/3f6faa49/src/tests/containerizer/docker_containerizer_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/containerizer/docker_containerizer_tests.cpp 
b/src/tests/containerizer/docker_containerizer_tests.cpp
index cca3f80..08bacb9 100644
--- a/src/tests/containerizer/docker_containerizer_tests.cpp
+++ b/src/tests/containerizer/docker_containerizer_tests.cpp
@@ -274,13 +274,14 @@ TEST_F(DockerContainerizerTest, 
ROOT_DOCKER_Launch_Executor)
 
   ASSERT_TRUE(exists(docker, slaveId, containerId.get()));
 
-  Future<ContainerTermination> termination =
+  Future<Option<ContainerTermination>> termination =
     dockerContainerizer.wait(containerId.get());
 
   driver.stop();
   driver.join();
 
   AWAIT_READY(termination);
+  EXPECT_SOME(termination.get());
 
   ASSERT_FALSE(
     exists(docker, slaveId, containerId.get(), ContainerState::RUNNING));
@@ -402,13 +403,14 @@ TEST_F(DockerContainerizerTest, 
DISABLED_ROOT_DOCKER_Launch_Executor_Bridged)
 
   ASSERT_TRUE(exists(docker, slaveId, containerId.get()));
 
-  Future<ContainerTermination> termination =
+  Future<Option<ContainerTermination>> termination =
     dockerContainerizer.wait(containerId.get());
 
   driver.stop();
   driver.join();
 
   AWAIT_READY(termination);
+  EXPECT_SOME(termination.get());
 
   ASSERT_FALSE(
     exists(docker, slaveId, containerId.get(), ContainerState::RUNNING));
@@ -553,13 +555,14 @@ TEST_F(DockerContainerizerTest, ROOT_DOCKER_Launch)
 
   ASSERT_TRUE(exists(docker, slaveId, containerId.get()));
 
-  Future<ContainerTermination> termination =
+  Future<Option<ContainerTermination>> termination =
     dockerContainerizer.wait(containerId.get());
 
   driver.stop();
   driver.join();
 
   AWAIT_READY(termination);
+  EXPECT_SOME(termination.get());
 
   ASSERT_FALSE(
     exists(docker, slaveId, containerId.get(), ContainerState::RUNNING));
@@ -664,7 +667,7 @@ TEST_F(DockerContainerizerTest, ROOT_DOCKER_Kill)
   EXPECT_CALL(sched, statusUpdate(&driver, _))
     .WillOnce(FutureArg<1>(&statusKilled));
 
-  Future<ContainerTermination> termination =
+  Future<Option<ContainerTermination>> termination =
     dockerContainerizer.wait(containerId.get());
 
   driver.killTask(task.task_id());
@@ -673,6 +676,7 @@ TEST_F(DockerContainerizerTest, ROOT_DOCKER_Kill)
   EXPECT_EQ(TASK_KILLED, statusKilled.get().state());
 
   AWAIT_READY(termination);
+  EXPECT_SOME(termination.get());
 
   ASSERT_FALSE(
     exists(docker, slaveId, containerId.get(), ContainerState::RUNNING));
@@ -790,7 +794,7 @@ TEST_F(DockerContainerizerTest, 
ROOT_DOCKER_TaskKillingCapability)
     .WillOnce(FutureArg<1>(&statusKilling))
     .WillOnce(FutureArg<1>(&statusKilled));
 
-  Future<ContainerTermination> termination =
+  Future<Option<ContainerTermination>> termination =
     dockerContainerizer.wait(containerId.get());
 
   driver.killTask(task.task_id());
@@ -802,6 +806,7 @@ TEST_F(DockerContainerizerTest, 
ROOT_DOCKER_TaskKillingCapability)
   EXPECT_EQ(TASK_KILLED, statusKilled->state());
 
   AWAIT_READY(termination);
+  EXPECT_SOME(termination.get());
 
   ASSERT_FALSE(
     exists(docker, slaveId, containerId.get(), ContainerState::RUNNING));
@@ -939,12 +944,13 @@ TEST_F(DockerContainerizerTest, ROOT_DOCKER_Usage)
   EXPECT_LT(0, statistics.cpus_system_time_secs());
   EXPECT_GT(statistics.mem_rss_bytes(), 0u);
 
-  Future<ContainerTermination> termination =
+  Future<Option<ContainerTermination>> termination =
     dockerContainerizer.wait(containerId.get());
 
   dockerContainerizer.destroy(containerId.get());
 
   AWAIT_READY(termination);
+  EXPECT_SOME(termination.get());
 
   // Usage() should fail again since the container is destroyed.
   Future<ResourceStatistics> usage =
@@ -1231,7 +1237,7 @@ TEST_F(DockerContainerizerTest, ROOT_DOCKER_Recover)
 
   AWAIT_READY(recover);
 
-  Future<ContainerTermination> termination =
+  Future<Option<ContainerTermination>> termination =
     dockerContainerizer.wait(containerId);
 
   ASSERT_FALSE(termination.isFailed());
@@ -1362,7 +1368,7 @@ TEST_F(DockerContainerizerTest, 
ROOT_DOCKER_KillOrphanContainers)
 
   AWAIT_READY(recover);
 
-  Future<ContainerTermination> termination =
+  Future<Option<ContainerTermination>> termination =
     dockerContainerizer.wait(containerId);
 
   ASSERT_FALSE(termination.isFailed());
@@ -1565,13 +1571,14 @@ TEST_F(DockerContainerizerTest, 
ROOT_DOCKER_LaunchWithPersistentVolumes)
   AWAIT_READY(statusFinished);
   EXPECT_EQ(TASK_FINISHED, statusFinished.get().state());
 
-  Future<ContainerTermination> termination =
+  Future<Option<ContainerTermination>> termination =
     dockerContainerizer.wait(containerId.get());
 
   driver.stop();
   driver.join();
 
   AWAIT_READY(termination);
+  EXPECT_SOME(termination.get());
 
   ASSERT_FALSE(
     exists(docker, slaveId, containerId.get(), ContainerState::RUNNING));
@@ -1735,12 +1742,13 @@ TEST_F(DockerContainerizerTest, 
ROOT_DOCKER_RecoverPersistentVolumes)
   // Wait until containerizer recover is complete.
   AWAIT_READY(_recover);
 
-  Future<ContainerTermination> termination =
+  Future<Option<ContainerTermination>> termination =
     dockerContainerizer->wait(containerId.get());
 
   dockerContainerizer->destroy(containerId.get());
 
   AWAIT_READY(termination);
+  EXPECT_SOME(termination.get());
 
   Try<fs::MountInfoTable> table = fs::MountInfoTable::read();
   EXPECT_SOME(table);
@@ -2612,13 +2620,14 @@ TEST_F(DockerContainerizerTest, 
ROOT_DOCKER_SlaveRecoveryTaskContainer)
 
   ASSERT_TRUE(exists(docker, slaveId, containerId.get()));
 
-  Future<ContainerTermination> termination =
+  Future<Option<ContainerTermination>> termination =
     dockerContainerizer->wait(containerId.get());
 
   driver.stop();
   driver.join();
 
   AWAIT_READY(termination);
+  EXPECT_SOME(termination.get());
 }
 
 
@@ -2949,13 +2958,14 @@ TEST_F(DockerContainerizerTest, 
ROOT_DOCKER_NC_PortMapping)
   // to stdout by the docker container running nc -l.
   EXPECT_TRUE(containsLine(lines, uuid));
 
-  Future<ContainerTermination> termination =
+  Future<Option<ContainerTermination>> termination =
     dockerContainerizer.wait(containerId.get());
 
   driver.stop();
   driver.join();
 
   AWAIT_READY(termination);
+  EXPECT_SOME(termination.get());
 }
 
 
@@ -3057,13 +3067,14 @@ TEST_F(DockerContainerizerTest, 
ROOT_DOCKER_LaunchSandboxWithColon)
 
   ASSERT_TRUE(exists(docker, slaveId, containerId.get()));
 
-  Future<ContainerTermination> termination =
+  Future<Option<ContainerTermination>> termination =
     dockerContainerizer.wait(containerId.get());
 
   driver.stop();
   driver.join();
 
   AWAIT_READY(termination);
+  EXPECT_SOME(termination.get());
 }
 
 
@@ -3756,6 +3767,33 @@ TEST_F(DockerContainerizerTest, 
ROOT_DOCKER_DockerInspectDiscard)
   driver.join();
 }
 
+
+// Ensures the containerizer responds correctly (returns None)
+// to a request to wait on an unknown container.
+TEST_F(DockerContainerizerTest, ROOT_DOCKER_WaitUnknownContainer)
+{
+  slave::Flags flags = CreateSlaveFlags();
+
+  Fetcher fetcher;
+
+  Try<DockerContainerizer*> create =
+    DockerContainerizer::create(flags, &fetcher);
+
+  ASSERT_SOME(create);
+
+  DockerContainerizer* containerizer = create.get();
+
+  AWAIT_READY(containerizer->recover(None()));
+
+  ContainerID containerId;
+  containerId.set_value(UUID::random().toString());
+
+  Future<Option<ContainerTermination>> wait = containerizer->wait(containerId);
+
+  AWAIT_READY(wait);
+  EXPECT_NONE(wait.get());
+}
+
 } // namespace tests {
 } // namespace internal {
 } // namespace mesos {

http://git-wip-us.apache.org/repos/asf/mesos/blob/3f6faa49/src/tests/containerizer/filesystem_isolator_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/containerizer/filesystem_isolator_tests.cpp 
b/src/tests/containerizer/filesystem_isolator_tests.cpp
index df4642d..680d68b 100644
--- a/src/tests/containerizer/filesystem_isolator_tests.cpp
+++ b/src/tests/containerizer/filesystem_isolator_tests.cpp
@@ -288,12 +288,15 @@ TEST_F(LinuxFilesystemIsolatorTest, 
ROOT_ChangeRootFilesystem)
   AWAIT_READY_FOR(launch, Seconds(60));
 
   // Wait on the container.
-  Future<ContainerTermination> wait = containerizer.get()->wait(containerId);
+  Future<Option<ContainerTermination>> wait =
+    containerizer.get()->wait(containerId);
+
   AWAIT_READY(wait);
+  ASSERT_SOME(wait.get());
 
   // Check the executor exited correctly.
-  EXPECT_TRUE(wait.get().has_status());
-  EXPECT_EQ(0, wait.get().status());
+  EXPECT_TRUE(wait->get().has_status());
+  EXPECT_EQ(0, wait->get().status());
 }
 
 
@@ -807,12 +810,15 @@ TEST_F(LinuxFilesystemIsolatorTest, ROOT_Metrics)
   containerizer.get()->destroy(containerId);
 
   // Wait on the container.
-  Future<ContainerTermination> wait = containerizer.get()->wait(containerId);
+  Future<Option<ContainerTermination>> wait =
+    containerizer.get()->wait(containerId);
+
   AWAIT_READY(wait);
+  ASSERT_SOME(wait.get());
 
   // Executor was killed.
-  EXPECT_TRUE(wait.get().has_status());
-  EXPECT_EQ(9, wait.get().status());
+  EXPECT_TRUE(wait->get().has_status());
+  EXPECT_EQ(9, wait->get().status());
 }
 
 
@@ -858,12 +864,15 @@ TEST_F(LinuxFilesystemIsolatorTest, 
ROOT_VolumeFromSandbox)
   AWAIT_READY_FOR(launch, Seconds(60));
 
   // Wait on the container.
-  Future<ContainerTermination> wait = containerizer.get()->wait(containerId);
+  Future<Option<ContainerTermination>> wait =
+    containerizer.get()->wait(containerId);
+
   AWAIT_READY(wait);
+  ASSERT_SOME(wait.get());
 
   // Check the executor exited correctly.
-  EXPECT_TRUE(wait.get().has_status());
-  EXPECT_EQ(0, wait.get().status());
+  EXPECT_TRUE(wait->get().has_status());
+  EXPECT_EQ(0, wait->get().status());
 
   EXPECT_SOME_EQ("abc\n", os::read(path::join(directory, "tmp", "file")));
 }
@@ -911,12 +920,15 @@ TEST_F(LinuxFilesystemIsolatorTest, ROOT_VolumeFromHost)
   AWAIT_READY_FOR(launch, Seconds(60));
 
   // Wait on the container.
-  Future<ContainerTermination> wait = containerizer.get()->wait(containerId);
+  Future<Option<ContainerTermination>> wait =
+    containerizer.get()->wait(containerId);
+
   AWAIT_READY(wait);
+  ASSERT_SOME(wait.get());
 
   // Check the executor exited correctly.
-  EXPECT_TRUE(wait.get().has_status());
-  EXPECT_EQ(0, wait.get().status());
+  EXPECT_TRUE(wait->get().has_status());
+  EXPECT_EQ(0, wait->get().status());
 }
 
 
@@ -962,12 +974,15 @@ TEST_F(LinuxFilesystemIsolatorTest, 
ROOT_FileVolumeFromHost)
 
   AWAIT_READY_FOR(launch, Seconds(60));
 
-  Future<ContainerTermination> wait = containerizer.get()->wait(containerId);
+  Future<Option<ContainerTermination>> wait =
+    containerizer.get()->wait(containerId);
+
   AWAIT_READY(wait);
+  ASSERT_SOME(wait.get());
 
   // Check the executor exited correctly.
-  EXPECT_TRUE(wait.get().has_status());
-  EXPECT_EQ(0, wait.get().status());
+  EXPECT_TRUE(wait->get().has_status());
+  EXPECT_EQ(0, wait->get().status());
 }
 
 
@@ -1013,12 +1028,15 @@ TEST_F(LinuxFilesystemIsolatorTest, 
ROOT_VolumeFromHostSandboxMountPoint)
   AWAIT_READY_FOR(launch, Seconds(60));
 
   // Wait on the container.
-  Future<ContainerTermination> wait = containerizer.get()->wait(containerId);
+  Future<Option<ContainerTermination>> wait =
+    containerizer.get()->wait(containerId);
+
   AWAIT_READY(wait);
+  ASSERT_SOME(wait.get());
 
   // Check the executor exited correctly.
-  EXPECT_TRUE(wait.get().has_status());
-  EXPECT_EQ(0, wait.get().status());
+  EXPECT_TRUE(wait->get().has_status());
+  EXPECT_EQ(0, wait->get().status());
 }
 
 
@@ -1064,12 +1082,15 @@ TEST_F(LinuxFilesystemIsolatorTest, 
ROOT_FileVolumeFromHostSandboxMountPoint)
 
   AWAIT_READY_FOR(launch, Seconds(60));
 
-  Future<ContainerTermination> wait = containerizer.get()->wait(containerId);
+  Future<Option<ContainerTermination>> wait =
+    containerizer.get()->wait(containerId);
+
   AWAIT_READY(wait);
+  ASSERT_SOME(wait.get());
 
   // Check the executor exited correctly.
-  EXPECT_TRUE(wait.get().has_status());
-  EXPECT_EQ(0, wait.get().status());
+  EXPECT_TRUE(wait->get().has_status());
+  EXPECT_EQ(0, wait->get().status());
 }
 
 
@@ -1130,12 +1151,15 @@ TEST_F(LinuxFilesystemIsolatorTest, 
ROOT_PersistentVolumeWithRootFilesystem)
   AWAIT_READY_FOR(launch, Seconds(60));
 
   // Wait on the container.
-  Future<ContainerTermination> wait = containerizer.get()->wait(containerId);
+  Future<Option<ContainerTermination>> wait =
+    containerizer.get()->wait(containerId);
+
   AWAIT_READY(wait);
+  ASSERT_SOME(wait.get());
 
   // Check the executor exited correctly.
-  EXPECT_TRUE(wait.get().has_status());
-  EXPECT_EQ(0, wait.get().status());
+  EXPECT_TRUE(wait->get().has_status());
+  EXPECT_EQ(0, wait->get().status());
 
   EXPECT_SOME_EQ("abc\n", os::read(path::join(volume, "file")));
 }
@@ -1202,12 +1226,15 @@ TEST_F(LinuxFilesystemIsolatorTest, 
ROOT_PersistentVolumeWithoutRootFilesystem)
   AWAIT_READY_FOR(launch, Seconds(60));
 
   // Wait on the container.
-  Future<ContainerTermination> wait = containerizer.get()->wait(containerId);
+  Future<Option<ContainerTermination>> wait =
+    containerizer.get()->wait(containerId);
+
   AWAIT_READY(wait);
+  ASSERT_SOME(wait.get());
 
   // Check the executor exited correctly.
-  EXPECT_TRUE(wait.get().has_status());
-  EXPECT_EQ(0, wait.get().status());
+  EXPECT_TRUE(wait->get().has_status());
+  EXPECT_EQ(0, wait->get().status());
 
   EXPECT_SOME_EQ("abc\n", os::read(path::join(volume, "file")));
 }
@@ -1255,12 +1282,15 @@ TEST_F(LinuxFilesystemIsolatorTest, 
ROOT_ImageInVolumeWithoutRootFilesystem)
   AWAIT_READY_FOR(launch, Seconds(60));
 
   // Wait on the container.
-  Future<ContainerTermination> wait = containerizer.get()->wait(containerId);
+  Future<Option<ContainerTermination>> wait =
+    containerizer.get()->wait(containerId);
+
   AWAIT_READY(wait);
+  ASSERT_SOME(wait.get());
 
   // Check the executor exited correctly.
-  EXPECT_TRUE(wait.get().has_status());
-  EXPECT_EQ(0, wait.get().status());
+  EXPECT_TRUE(wait->get().has_status());
+  EXPECT_EQ(0, wait->get().status());
 }
 
 
@@ -1308,14 +1338,16 @@ TEST_F(LinuxFilesystemIsolatorTest, 
ROOT_ImageInVolumeWithRootFilesystem)
   AWAIT_READY_FOR(launch, Seconds(240));
 
   // Wait on the container.
-  Future<ContainerTermination> wait = containerizer.get()->wait(containerId);
+  Future<Option<ContainerTermination>> wait =
+    containerizer.get()->wait(containerId);
 
   // Because destroy rootfs spents a lot of time, we use 30s as timeout here.
   AWAIT_READY_FOR(wait, Seconds(30));
+  ASSERT_SOME(wait.get());
 
   // Check the executor exited correctly.
-  EXPECT_TRUE(wait.get().has_status());
-  EXPECT_EQ(0, wait.get().status());
+  EXPECT_TRUE(wait->get().has_status());
+  EXPECT_EQ(0, wait->get().status());
 }
 
 
@@ -1422,19 +1454,25 @@ TEST_F(LinuxFilesystemIsolatorTest, 
ROOT_MultipleContainers)
   containerizer.get()->destroy(containerId1);
 
   // Wait on the containers.
-  Future<ContainerTermination> wait1 = containerizer.get()->wait(containerId1);
-  Future<ContainerTermination> wait2 = containerizer.get()->wait(containerId2);
+  Future<Option<ContainerTermination>> wait1 =
+    containerizer.get()->wait(containerId1);
+
+  Future<Option<ContainerTermination>> wait2 =
+    containerizer.get()->wait(containerId2);
 
   AWAIT_READY_FOR(wait1, Seconds(60));
+  ASSERT_SOME(wait1.get());
+
   AWAIT_READY_FOR(wait2, Seconds(60));
+  ASSERT_SOME(wait2.get());
 
   // Executor 1 was forcefully killed.
-  EXPECT_TRUE(wait1.get().has_status());
-  EXPECT_EQ(9, wait1.get().status());
+  EXPECT_TRUE(wait1->get().has_status());
+  EXPECT_EQ(9, wait1->get().status());
 
   // Executor 2 exited normally.
-  EXPECT_TRUE(wait2.get().has_status());
-  EXPECT_EQ(0, wait2.get().status());
+  EXPECT_TRUE(wait2->get().has_status());
+  EXPECT_EQ(0, wait2->get().status());
 }
 
 
@@ -1493,12 +1531,15 @@ TEST_F(LinuxFilesystemIsolatorTest, 
ROOT_SandboxEnvironmentVariable)
   AWAIT_READY_FOR(launch, Seconds(60));
 
   // Wait on the container.
-  Future<ContainerTermination> wait = containerizer.get()->wait(containerId);
+  Future<Option<ContainerTermination>> wait =
+    containerizer.get()->wait(containerId);
+
   AWAIT_READY(wait);
+  ASSERT_SOME(wait.get());
 
   // Check the executor exited correctly.
-  EXPECT_TRUE(wait.get().has_status());
-  EXPECT_EQ(0, wait.get().status());
+  EXPECT_TRUE(wait->get().has_status());
+  EXPECT_EQ(0, wait->get().status());
 }
 
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/3f6faa49/src/tests/containerizer/isolator_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/containerizer/isolator_tests.cpp 
b/src/tests/containerizer/isolator_tests.cpp
index 56af742..b4d25e5 100644
--- a/src/tests/containerizer/isolator_tests.cpp
+++ b/src/tests/containerizer/isolator_tests.cpp
@@ -339,12 +339,13 @@ TEST_F(NamespacesPidIsolatorTest, ROOT_PidNamespace)
   ASSERT_TRUE(launch.get());
 
   // Wait on the container.
-  Future<ContainerTermination> wait = containerizer->wait(containerId);
+  Future<Option<ContainerTermination>> wait = containerizer->wait(containerId);
   AWAIT_READY(wait);
+  ASSERT_SOME(wait.get());
 
   // Check the executor exited correctly.
-  EXPECT_TRUE(wait.get().has_status());
-  EXPECT_EQ(0, wait.get().status());
+  EXPECT_TRUE(wait->get().has_status());
+  EXPECT_EQ(0, wait->get().status());
 
   // Check that the command was run in a different pid namespace.
   Try<ino_t> testPidNamespace = ns::getns(::getpid(), "pid");

http://git-wip-us.apache.org/repos/asf/mesos/blob/3f6faa49/src/tests/containerizer/mesos_containerizer_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/containerizer/mesos_containerizer_tests.cpp 
b/src/tests/containerizer/mesos_containerizer_tests.cpp
index 96e2450..d7455d2 100644
--- a/src/tests/containerizer/mesos_containerizer_tests.cpp
+++ b/src/tests/containerizer/mesos_containerizer_tests.cpp
@@ -220,12 +220,15 @@ TEST_F(MesosContainerizerIsolatorPreparationTest, 
ScriptSucceeds)
   AWAIT_READY(launch);
 
   // Wait for the child (preparation script + executor) to complete.
-  Future<ContainerTermination> wait = containerizer.get()->wait(containerId);
+  Future<Option<ContainerTermination>> wait =
+    containerizer.get()->wait(containerId);
+
   AWAIT_READY(wait);
+  ASSERT_SOME(wait.get());
 
   // Check the child exited correctly.
-  EXPECT_TRUE(wait.get().has_status());
-  EXPECT_EQ(0, wait.get().status());
+  EXPECT_TRUE(wait->get().has_status());
+  EXPECT_EQ(0, wait->get().status());
 
   // Check the preparation script actually ran.
   EXPECT_TRUE(os::exists(file));
@@ -270,12 +273,15 @@ TEST_F(MesosContainerizerIsolatorPreparationTest, 
ScriptFails)
   AWAIT_READY(launch);
 
   // Wait for the child (preparation script + executor) to complete.
-  Future<ContainerTermination> wait = containerizer.get()->wait(containerId);
+  Future<Option<ContainerTermination>> wait =
+    containerizer.get()->wait(containerId);
+
   AWAIT_READY(wait);
+  ASSERT_SOME(wait.get());
 
   // Check the child failed to exit correctly.
-  EXPECT_TRUE(wait.get().has_status());
-  EXPECT_NE(0, wait.get().status());
+  EXPECT_TRUE(wait->get().has_status());
+  EXPECT_NE(0, wait->get().status());
 
   // Check the preparation script actually ran.
   EXPECT_TRUE(os::exists(file));
@@ -331,12 +337,15 @@ TEST_F(MesosContainerizerIsolatorPreparationTest, 
MultipleScripts)
   AWAIT_READY(launch);
 
   // Wait for the child (preparation script(s) + executor) to complete.
-  Future<ContainerTermination> wait = containerizer.get()->wait(containerId);
+  Future<Option<ContainerTermination>> wait =
+    containerizer.get()->wait(containerId);
+
   AWAIT_READY(wait);
+  ASSERT_SOME(wait.get());
 
   // Check the child failed to exit correctly.
-  EXPECT_TRUE(wait.get().has_status());
-  EXPECT_NE(0, wait.get().status());
+  EXPECT_TRUE(wait->get().has_status());
+  EXPECT_NE(0, wait->get().status());
 
   // Check the failing preparation script has actually ran.
   EXPECT_TRUE(os::exists(file2));
@@ -412,12 +421,15 @@ TEST_F(MesosContainerizerIsolatorPreparationTest, 
ExecutorEnvironmentVariable)
   AWAIT_READY(launch);
 
   // Wait for the child (preparation script + executor) to complete.
-  Future<ContainerTermination> wait = containerizer.get()->wait(containerId);
+  Future<Option<ContainerTermination>> wait =
+    containerizer.get()->wait(containerId);
+
   AWAIT_READY(wait);
+  ASSERT_SOME(wait.get());
 
   // Check the child exited correctly.
-  EXPECT_TRUE(wait.get().has_status());
-  EXPECT_EQ(0, wait.get().status());
+  EXPECT_TRUE(wait->get().has_status());
+  EXPECT_EQ(0, wait->get().status());
 
   // Check the preparation script actually ran.
   EXPECT_TRUE(os::exists(file));
@@ -480,12 +492,15 @@ TEST_F(MesosContainerizerExecuteTest, IoRedirection)
   AWAIT_READY(launch);
 
   // Wait on the container.
-  Future<ContainerTermination> wait = containerizer->wait(containerId);
+  Future<Option<ContainerTermination>> wait =
+    containerizer->wait(containerId);
+
   AWAIT_READY(wait);
+  ASSERT_SOME(wait.get());
 
   // Check the executor exited correctly.
-  EXPECT_TRUE(wait.get().has_status());
-  EXPECT_EQ(0, wait.get().status());
+  EXPECT_TRUE(wait->get().has_status());
+  EXPECT_EQ(0, wait->get().status());
 
   // Check that std{err, out} was redirected.
   // NOTE: Fetcher uses GLOG, which outputs extra information to
@@ -661,13 +676,16 @@ TEST_F(MesosContainerizerDestroyTest, 
DestroyWhileFetching)
       map<string, string>(),
       false);
 
-  Future<ContainerTermination> wait = containerizer.wait(containerId);
+  Future<Option<ContainerTermination>> wait =
+    containerizer.wait(containerId);
+
   AWAIT_READY(exec);
 
   containerizer.destroy(containerId);
 
   // The container should still exit even if fetch didn't complete.
   AWAIT_READY(wait);
+  EXPECT_SOME(wait.get());
 }
 
 
@@ -728,7 +746,8 @@ TEST_F(MesosContainerizerDestroyTest, DestroyWhilePreparing)
       map<string, string>(),
       false);
 
-  Future<ContainerTermination> wait = containerizer.wait(containerId);
+  Future<Option<ContainerTermination>> wait =
+    containerizer.wait(containerId);
 
   AWAIT_READY(prepare);
 
@@ -744,8 +763,9 @@ TEST_F(MesosContainerizerDestroyTest, DestroyWhilePreparing)
   promise.set(option);
 
   AWAIT_READY(wait);
+  ASSERT_SOME(wait.get());
 
-  ContainerTermination termination = wait.get();
+  ContainerTermination termination = wait->get();
 
   EXPECT_FALSE(termination.has_status());
 }
@@ -849,13 +869,15 @@ TEST_F(MesosContainerizerProvisionerTest, ProvisionFailed)
 
   AWAIT_FAILED(launch);
 
-  Future<ContainerTermination> wait = containerizer.wait(containerId);
+  Future<Option<ContainerTermination>> wait =
+    containerizer.wait(containerId);
 
   containerizer.destroy(containerId);
 
   AWAIT_READY(wait);
+  ASSERT_SOME(wait.get());
 
-  ContainerTermination termination = wait.get();
+  ContainerTermination termination = wait->get();
 
   EXPECT_FALSE(termination.has_status());
 }
@@ -937,7 +959,8 @@ TEST_F(MesosContainerizerProvisionerTest, 
DestroyWhileProvisioning)
       map<string, string>(),
       false);
 
-  Future<ContainerTermination> wait = containerizer.wait(containerId);
+  Future<Option<ContainerTermination>> wait =
+    containerizer.wait(containerId);
 
   AWAIT_READY(provision);
 
@@ -948,8 +971,9 @@ TEST_F(MesosContainerizerProvisionerTest, 
DestroyWhileProvisioning)
 
   AWAIT_FAILED(launch);
   AWAIT_READY(wait);
+  ASSERT_SOME(wait.get());
 
-  ContainerTermination termination = wait.get();
+  ContainerTermination termination = wait->get();
 
   EXPECT_FALSE(termination.has_status());
 }
@@ -1036,7 +1060,8 @@ TEST_F(MesosContainerizerProvisionerTest, 
IsolatorCleanupBeforePrepare)
       map<string, string>(),
       false);
 
-  Future<ContainerTermination> wait = containerizer.wait(containerId);
+  Future<Option<ContainerTermination>> wait =
+    containerizer.wait(containerId);
 
   AWAIT_READY(provision);
 
@@ -1047,8 +1072,9 @@ TEST_F(MesosContainerizerProvisionerTest, 
IsolatorCleanupBeforePrepare)
 
   AWAIT_FAILED(launch);
   AWAIT_READY(wait);
+  ASSERT_SOME(wait.get());
 
-  ContainerTermination termination = wait.get();
+  ContainerTermination termination = wait->get();
 
   EXPECT_FALSE(termination.has_status());
 }
@@ -1121,7 +1147,8 @@ TEST_F(MesosContainerizerDestroyTest, 
LauncherDestroyFailure)
 
   AWAIT_READY(launch);
 
-  Future<ContainerTermination> wait = containerizer.wait(containerId);
+  Future<Option<ContainerTermination>> wait =
+    containerizer.wait(containerId);
 
   containerizer.destroy(containerId);
 
@@ -1239,6 +1266,34 @@ TEST_F(MesosLauncherStatusTest, ExecutorPIDTest)
   AWAIT_READY(launcher.get()->destroy(containerId));
 }
 
+
+class MesosContainerizerWaitTest : public MesosTest {};
+
+
+// Ensures the containerizer responds correctly (returns None)
+// to a request to wait on an unknown container.
+TEST_F(MesosContainerizerWaitTest, WaitUnknownContainer)
+{
+  slave::Flags flags = CreateSlaveFlags();
+
+  Fetcher fetcher;
+
+  Try<MesosContainerizer*> create =
+    MesosContainerizer::create(flags, true, &fetcher);
+
+  ASSERT_SOME(create);
+
+  MesosContainerizer* containerizer = create.get();
+
+  ContainerID containerId;
+  containerId.set_value(UUID::random().toString());
+
+  Future<Option<ContainerTermination>> wait = containerizer->wait(containerId);
+
+  AWAIT_READY(wait);
+  EXPECT_NONE(wait.get());
+}
+
 } // namespace tests {
 } // namespace internal {
 } // namespace mesos {

http://git-wip-us.apache.org/repos/asf/mesos/blob/3f6faa49/src/tests/containerizer/port_mapping_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/containerizer/port_mapping_tests.cpp 
b/src/tests/containerizer/port_mapping_tests.cpp
index ab8db58..99790d0 100644
--- a/src/tests/containerizer/port_mapping_tests.cpp
+++ b/src/tests/containerizer/port_mapping_tests.cpp
@@ -2197,7 +2197,8 @@ TEST_F(PortMappingMesosTest, 
ROOT_NetworkNamespaceHandleSymlink)
   EXPECT_TRUE(os::exists(symlink));
   EXPECT_TRUE(os::stat::islink(symlink));
 
-  Future<ContainerTermination> termination = containerizer->wait(containerId);
+  Future<Option<ContainerTermination>> termination =
+    containerizer->wait(containerId);
 
   driver.killTask(task.task_id());
 
@@ -2206,6 +2207,8 @@ TEST_F(PortMappingMesosTest, 
ROOT_NetworkNamespaceHandleSymlink)
   EXPECT_EQ(TASK_KILLED, status2.get().state());
 
   AWAIT_READY(termination);
+  EXPECT_SOME(termination.get());
+
   EXPECT_FALSE(os::exists(symlink));
 
   driver.stop();

http://git-wip-us.apache.org/repos/asf/mesos/blob/3f6faa49/src/tests/health_check_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/health_check_tests.cpp b/src/tests/health_check_tests.cpp
index 30b5a2f..e6b02f2 100644
--- a/src/tests/health_check_tests.cpp
+++ b/src/tests/health_check_tests.cpp
@@ -580,13 +580,14 @@ TEST_F(HealthCheckTest, ROOT_DOCKER_DockerHealthyTask)
   EXPECT_TRUE(statusHealth.get().has_healthy());
   EXPECT_TRUE(statusHealth.get().healthy());
 
-  Future<ContainerTermination> termination =
+  Future<Option<ContainerTermination>> termination =
     containerizer.wait(containerId.get());
 
   driver.stop();
   driver.join();
 
   AWAIT_READY(termination);
+  EXPECT_SOME(termination.get());
 
   slave.get()->terminate();
   slave->reset();
@@ -1003,13 +1004,14 @@ TEST_F(HealthCheckTest, 
ROOT_DOCKER_DockerHealthStatusChange)
   ASSERT_SOME(os::read(tmpPath));
   EXPECT_EQ("bar", os::read(tmpPath).get());
 
-  Future<ContainerTermination> termination =
+  Future<Option<ContainerTermination>> termination =
     containerizer.wait(containerId.get());
 
   driver.stop();
   driver.join();
 
   AWAIT_READY(termination);
+  EXPECT_SOME(termination.get());
 
   slave.get()->terminate();
   slave->reset();

http://git-wip-us.apache.org/repos/asf/mesos/blob/3f6faa49/src/tests/hook_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/hook_tests.cpp b/src/tests/hook_tests.cpp
index 602bb39..f837ca7 100644
--- a/src/tests/hook_tests.cpp
+++ b/src/tests/hook_tests.cpp
@@ -324,12 +324,15 @@ TEST_F(HookTest, VerifySlaveExecutorEnvironmentDecorator)
   ASSERT_TRUE(launch.get());
 
   // Wait on the container.
-  process::Future<ContainerTermination> wait = 
containerizer->wait(containerId);
+  Future<Option<ContainerTermination>> wait =
+    containerizer->wait(containerId);
+
   AWAIT_READY(wait);
+  ASSERT_SOME(wait.get());
 
   // Check the executor exited correctly.
-  EXPECT_TRUE(wait.get().has_status());
-  EXPECT_EQ(0, wait.get().status());
+  EXPECT_TRUE(wait->get().has_status());
+  EXPECT_EQ(0, wait->get().status());
 }
 
 
@@ -712,13 +715,14 @@ TEST_F(HookTest, 
ROOT_DOCKER_VerifySlavePreLaunchDockerEnvironmentDecorator)
   AWAIT_READY_FOR(statusFinished, Seconds(60));
   EXPECT_EQ(TASK_FINISHED, statusFinished.get().state());
 
-  Future<ContainerTermination> termination =
+  Future<Option<ContainerTermination>> termination =
     containerizer.wait(containerId.get());
 
   driver.stop();
   driver.join();
 
   AWAIT_READY(termination);
+  EXPECT_SOME(termination.get());
 
   Future<list<Docker::Container>> containers =
     docker.get()->ps(true, slave::DOCKER_NAME_PREFIX);
@@ -928,13 +932,14 @@ TEST_F(HookTest, 
ROOT_DOCKER_VerifySlavePreLaunchDockerHook)
   AWAIT_READY_FOR(statusFinished, Seconds(60));
   EXPECT_EQ(TASK_FINISHED, statusFinished.get().state());
 
-  Future<ContainerTermination> termination =
+  Future<Option<ContainerTermination>> termination =
     containerizer.wait(containerId.get());
 
   driver.stop();
   driver.join();
 
   AWAIT_READY(termination);
+  EXPECT_SOME(termination.get());
 
   Future<list<Docker::Container>> containers =
     docker.get()->ps(true, slave::DOCKER_NAME_PREFIX);

http://git-wip-us.apache.org/repos/asf/mesos/blob/3f6faa49/src/tests/slave_recovery_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/slave_recovery_tests.cpp 
b/src/tests/slave_recovery_tests.cpp
index 23cf9d8..618019c 100644
--- a/src/tests/slave_recovery_tests.cpp
+++ b/src/tests/slave_recovery_tests.cpp
@@ -1719,10 +1719,13 @@ TYPED_TEST(SlaveRecoveryTest, 
RemoveNonCheckpointingFramework)
   AWAIT_READY(containers);
 
   foreach (const ContainerID& containerId, containers.get()) {
-    Future<ContainerTermination> wait = containerizer.get()->wait(containerId);
+    Future<Option<ContainerTermination>> wait =
+      containerizer.get()->wait(containerId);
 
     containerizer.get()->destroy(containerId);
+
     AWAIT_READY(wait);
+    EXPECT_SOME(wait.get());
   }
 }
 
@@ -2652,10 +2655,13 @@ TYPED_TEST(SlaveRecoveryTest, RegisterDisconnectedSlave)
   AWAIT_READY(containers);
 
   foreach (const ContainerID& containerId, containers.get()) {
-    Future<ContainerTermination> wait = containerizer.get()->wait(containerId);
+    Future<Option<ContainerTermination>> wait =
+      containerizer.get()->wait(containerId);
 
     containerizer.get()->destroy(containerId);
+
     AWAIT_READY(wait);
+    EXPECT_SOME(wait.get());
   }
 }
 
@@ -3863,11 +3869,13 @@ TEST_F(MesosContainerizerSlaveRecoveryTest, 
ResourceStatistics)
   EXPECT_TRUE(usage.get().has_cpus_limit());
   EXPECT_TRUE(usage.get().has_mem_limit_bytes());
 
-  Future<ContainerTermination> wait = containerizer->wait(containerId);
+  Future<Option<ContainerTermination>> wait =
+    containerizer->wait(containerId);
 
   containerizer->destroy(containerId);
 
   AWAIT_READY(wait);
+  EXPECT_SOME(wait.get());
 
   driver.stop();
   driver.join();
@@ -4116,12 +4124,14 @@ TEST_F(MesosContainerizerSlaveRecoveryTest, 
CGROUPS_ROOT_PidNamespaceForward)
   EXPECT_NE(0u, offers2.get().size());
 
   // Set up to wait on the container's termination.
-  Future<ContainerTermination> termination = containerizer->wait(containerId);
+  Future<Option<ContainerTermination>> termination =
+    containerizer->wait(containerId);
 
   // Destroy the container.
   containerizer->destroy(containerId);
 
   AWAIT_READY(termination);
+  EXPECT_SOME(termination.get());
 
   driver.stop();
   driver.join();
@@ -4221,12 +4231,14 @@ TEST_F(MesosContainerizerSlaveRecoveryTest, 
CGROUPS_ROOT_PidNamespaceBackward)
   EXPECT_NE(0u, offers2.get().size());
 
   // Set up to wait on the container's termination.
-  Future<ContainerTermination> termination = containerizer->wait(containerId);
+  Future<Option<ContainerTermination>> termination =
+    containerizer->wait(containerId);
 
   // Destroy the container.
   containerizer->destroy(containerId);
 
   AWAIT_READY(termination);
+  EXPECT_SOME(termination.get());
 
   driver.stop();
   driver.join();

Reply via email to