You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by al...@apache.org on 2018/08/20 14:29:27 UTC

[mesos] 03/04: Added `ROOT_CGROUPS_LaunchNestedDebugAfterUnshareMntNamespace` test.

This is an automated email from the ASF dual-hosted git repository.

alexr pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mesos.git

commit 31499a5dc1de29fa2178e6ea9e5398d8c668a933
Author: Andrei Budnik <ab...@mesosphere.com>
AuthorDate: Mon Aug 20 16:28:38 2018 +0200

    Added `ROOT_CGROUPS_LaunchNestedDebugAfterUnshareMntNamespace` test.
    
    This test verifies detection of task's `mnt` namespace for a debug
    nested container. Debug nested container must enter `mnt` namespace
    of the task, so the agent tries to detect task's `mnt` namespace.
    This test launches a long-running task which runs a subtask that
    unshares `mnt` namespace. The structure of the resulting process tree
    is similar to the process tree of the command executor (the task of
    the command executor unshares `mnt` ns):
    
      0. root (aka "nanny"/"launcher" process) [root `mnt` namespace]
        1. task: sleep 1000 [root `mnt` namespace]
          2. subtaks: sleep 1000 [subtask's `mnt` namespace]
    
    We expect that the agent detects task's `mnt` namespace.
    
    Review: https://reviews.apache.org/r/68408/
---
 .../nested_mesos_containerizer_tests.cpp           | 107 +++++++++++++++++++++
 1 file changed, 107 insertions(+)

diff --git a/src/tests/containerizer/nested_mesos_containerizer_tests.cpp b/src/tests/containerizer/nested_mesos_containerizer_tests.cpp
index b80e40b..295dbc8 100644
--- a/src/tests/containerizer/nested_mesos_containerizer_tests.cpp
+++ b/src/tests/containerizer/nested_mesos_containerizer_tests.cpp
@@ -1050,6 +1050,113 @@ TEST_F(NestedMesosContainerizerTest,
 }
 
 
+// This test verifies detection of task's `mnt` namespace for a debug nested
+// container. Debug nested container must enter `mnt` namespace of the task,
+// so the agent tries to detect task's `mnt` namespace. This test launches
+// a long-running task which runs a subtask that unshares `mnt` namespace.
+// The structure of the resulting process tree is similar to the process tree
+// of the command executor (the task of command executor unshares `mnt` ns):
+//
+// 0. root (aka "nanny"/"launcher" process) [root `mnt` namespace]
+//   1. task: sleep 1000 [root `mnt` namespace]
+//     2. subtaks: sleep 1000 [subtask's `mnt` namespace]
+//
+// We expect that the agent detects task's `mnt` namespace.
+TEST_F(NestedMesosContainerizerTest,
+       ROOT_CGROUPS_LaunchNestedDebugAfterUnshareMntNamespace)
+{
+  slave::Flags flags = CreateSlaveFlags();
+  flags.launcher = "linux";
+  flags.isolation = "filesystem/linux";
+
+  Fetcher fetcher(flags);
+
+  Try<MesosContainerizer*> create = MesosContainerizer::create(
+      flags,
+      true,
+      &fetcher);
+
+  ASSERT_SOME(create);
+
+  Owned<MesosContainerizer> containerizer(create.get());
+
+  SlaveState state;
+  state.id = SlaveID();
+
+  AWAIT_READY(containerizer->recover(state));
+
+  // Launch the parent container.
+  ContainerID containerId;
+  containerId.set_value(id::UUID::random().toString());
+
+  string pipe = path::join(sandbox.get(), "pipe");
+  ASSERT_EQ(0, ::mkfifo(pipe.c_str(), 0700));
+
+  const string cmd =
+    "(unshare -m sh -c"
+    " 'mkdir -p test_mnt; mount tmpfs -t tmpfs test_mnt;"
+    " touch test_mnt/check; exec sleep 1000')&"
+    "echo running > " + pipe + "; exec sleep 1000";
+
+  ExecutorInfo executor = createExecutorInfo("executor", cmd, "cpus:1");
+
+  Try<string> directory = environment->mkdtemp();
+  ASSERT_SOME(directory);
+
+  Future<Containerizer::LaunchResult> launch = containerizer->launch(
+      containerId,
+      createContainerConfig(None(), executor, directory.get()),
+      map<string, string>(),
+      None());
+
+  AWAIT_ASSERT_EQ(Containerizer::LaunchResult::SUCCESS, launch);
+
+  // Wait for the parent container to start running its task
+  // before launching a debug nested container.
+  Result<string> read = os::read(pipe);
+  ASSERT_SOME(read);
+  ASSERT_EQ("running\n", read.get());
+
+  // Launch a nested debug container.
+  ContainerID nestedContainerId;
+  nestedContainerId.mutable_parent()->CopyFrom(containerId);
+  nestedContainerId.set_value(id::UUID::random().toString());
+
+  // Launch a debug container inside the command task and check for the
+  // absence of a file we know to be inside the subtask's mounted directory.
+  launch = containerizer->launch(
+      nestedContainerId,
+      createContainerConfig(
+          createCommandInfo(
+              "LINES=`ls -la test_mnt/check | wc -l`;"
+              "if [ ${LINES} -ne 0 ]; then"
+              "  exit 1;"
+              "fi;"),
+          None(),
+          ContainerClass::DEBUG),
+      map<string, string>(),
+      None());
+
+  AWAIT_ASSERT_EQ(Containerizer::LaunchResult::SUCCESS, launch);
+
+  Future<Option<ContainerTermination>> wait =
+    containerizer->wait(nestedContainerId);
+
+  AWAIT_READY(wait);
+  ASSERT_SOME(wait.get());
+  ASSERT_TRUE(wait.get()->has_status());
+  EXPECT_WEXITSTATUS_EQ(0, wait.get()->status());
+
+  Future<Option<ContainerTermination>> termination =
+    containerizer->destroy(containerId);
+
+  AWAIT_READY(termination);
+  ASSERT_SOME(termination.get());
+  ASSERT_TRUE(termination.get()->has_status());
+  EXPECT_WTERMSIG_EQ(SIGKILL, termination.get()->status());
+}
+
+
 TEST_F(NestedMesosContainerizerTest,
        ROOT_CGROUPS_DestroyDebugContainerOnRecover)
 {