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

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

commit 82305ea19b4fd1b04bdeb0d6f8bb1792077a6206
Author: Qian Zhang <[email protected]>
AuthorDate: Sat Jul 13 10:07:55 2019 -0700

    Added the test `NamespacesIsolatorTest.ROOT_ShareAgentIPCNamespace`.
    
    Review: https://reviews.apache.org/r/70852/
---
 src/tests/containerizer/isolator_tests.cpp | 122 +++++++++++++++++++++++++++++
 1 file changed, 122 insertions(+)

diff --git a/src/tests/containerizer/isolator_tests.cpp 
b/src/tests/containerizer/isolator_tests.cpp
index fad6eb4..75b9520 100644
--- a/src/tests/containerizer/isolator_tests.cpp
+++ b/src/tests/containerizer/isolator_tests.cpp
@@ -743,6 +743,128 @@ TEST_F(NamespacesIsolatorTest, ROOT_PrivateIPCNamespace)
   ASSERT_TRUE(termination.get()->has_status());
   EXPECT_WTERMSIG_EQ(SIGKILL, termination.get()->status());
 }
+
+
+// This test verifies that top-level container and nested
+// containers can share agent's IPC namespace and /dev/shm.
+TEST_F(NamespacesIsolatorTest, ROOT_ShareAgentIPCNamespace)
+{
+  Try<Owned<MesosContainerizer>> containerizer =
+    createContainerizer("filesystem/linux,namespaces/ipc");
+
+  ASSERT_SOME(containerizer);
+
+  // Launch a top-level container with `SHARE_PARENT` IPC mode,
+  // write its IPC namespace inode to a file under /dev/shm.
+  const string command =
+    "stat -Lc %i /proc/self/ns/ipc > /dev/shm/root && "
+    "sleep 1000";
+
+  mesos::slave::ContainerConfig containerConfig = createContainerConfig(
+      None(),
+      createExecutorInfo("executor", command),
+      directory);
+
+  ContainerInfo* container = containerConfig.mutable_container_info();
+  container->set_type(ContainerInfo::MESOS);
+  container->mutable_linux_info()->set_ipc_mode(LinuxInfo::SHARE_PARENT);
+
+  process::Future<Containerizer::LaunchResult> launch =
+    containerizer.get()->launch(
+        containerId,
+        containerConfig,
+        std::map<string, string>(),
+        None());
+
+  AWAIT_ASSERT_EQ(Containerizer::LaunchResult::SUCCESS, launch);
+
+  // Launch a nested container with `SHARE_PARENT` IPC mode,
+  // write its IPC namespace inode to a file under /dev/shm.
+  ContainerID nestedContainerId1;
+  nestedContainerId1.mutable_parent()->CopyFrom(containerId);
+  nestedContainerId1.set_value(id::UUID::random().toString());
+
+  ContainerInfo containerInfo;
+  containerInfo.set_type(ContainerInfo::MESOS);
+  containerInfo.mutable_linux_info()->set_ipc_mode(LinuxInfo::SHARE_PARENT);
+
+  launch = containerizer.get()->launch(
+      nestedContainerId1,
+      createContainerConfig(
+          createCommandInfo("stat -Lc %i /proc/self/ns/ipc > /dev/shm/nest1"),
+          containerInfo),
+      std::map<string, string>(),
+      None());
+
+  AWAIT_ASSERT_EQ(Containerizer::LaunchResult::SUCCESS, launch);
+
+  Future<Option<ContainerTermination>> wait = containerizer.get()->wait(
+      nestedContainerId1);
+
+  AWAIT_READY(wait);
+  ASSERT_SOME(wait.get());
+  ASSERT_TRUE(wait.get()->has_status());
+  EXPECT_WEXITSTATUS_EQ(0, wait.get()->status());
+
+  // Launch another nested container with `SHARE_PARENT` IPC mode and its
+  // own rootfs, write its IPC namespace inode to a file under /dev/shm.
+  ContainerID nestedContainerId2;
+  nestedContainerId2.mutable_parent()->CopyFrom(containerId);
+  nestedContainerId2.set_value(id::UUID::random().toString());
+
+  mesos::Image image;
+  image.set_type(mesos::Image::DOCKER);
+  image.mutable_docker()->set_name("alpine");
+
+  containerInfo.mutable_mesos()->mutable_image()->CopyFrom(image);
+
+  launch = containerizer.get()->launch(
+      nestedContainerId2,
+      createContainerConfig(
+          createCommandInfo("stat -Lc %i /proc/self/ns/ipc > /dev/shm/nest2"),
+          containerInfo),
+      std::map<string, string>(),
+      None());
+
+  AWAIT_ASSERT_EQ(Containerizer::LaunchResult::SUCCESS, launch);
+
+  wait = containerizer.get()->wait(nestedContainerId2);
+
+  AWAIT_READY(wait);
+  ASSERT_SOME(wait.get());
+  ASSERT_TRUE(wait.get()->has_status());
+  EXPECT_WEXITSTATUS_EQ(0, wait.get()->status());
+
+  // Check top-level container and the two nested containers
+  // share agent's IPC namespace and /dev/shm.
+  Try<uint64_t> rootIpcNamespace = readValue("/dev/shm/root");
+  ASSERT_SOME(rootIpcNamespace);
+
+  Try<uint64_t> nestedIpcNamespace1 = readValue("/dev/shm/nest1");
+  ASSERT_SOME(nestedIpcNamespace1);
+
+  Try<uint64_t> nestedIpcNamespace2 = readValue("/dev/shm/nest2");
+  ASSERT_SOME(nestedIpcNamespace2);
+
+  Result<ino_t> agentIpcNamespace = ns::getns(::getpid(), "ipc");
+  ASSERT_SOME(agentIpcNamespace);
+
+  EXPECT_EQ(rootIpcNamespace.get(), agentIpcNamespace.get());
+  EXPECT_EQ(nestedIpcNamespace1.get(), agentIpcNamespace.get());
+  EXPECT_EQ(nestedIpcNamespace2.get(), agentIpcNamespace.get());
+
+  Future<Option<ContainerTermination>> termination =
+    containerizer.get()->destroy(containerId);
+
+  AWAIT_READY(termination);
+  ASSERT_SOME(termination.get());
+  ASSERT_TRUE(termination.get()->has_status());
+  EXPECT_WTERMSIG_EQ(SIGKILL, termination.get()->status());
+
+  ASSERT_SOME(os::rm("/dev/shm/root"));
+  ASSERT_SOME(os::rm("/dev/shm/nest1"));
+  ASSERT_SOME(os::rm("/dev/shm/nest2"));
+}
 #endif // __linux__
 
 } // namespace tests {

Reply via email to