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 2016/01/25 05:13:44 UTC

[02/11] mesos git commit: Add test for the rotating container logger module.

Add test for the rotating container logger module.

This test loads a non-default ContainerLogger module that rotates logs
(i.e. renaming the head log file) and constrains total log size.

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


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

Branch: refs/heads/master
Commit: 0f20d5e73ebe7eacc154867c53aea4b16f548abf
Parents: b97d2ab
Author: Joseph Wu <jo...@mesosphere.io>
Authored: Wed Jan 20 16:48:43 2016 -0800
Committer: Benjamin Hindman <be...@gmail.com>
Committed: Sun Jan 24 20:13:22 2016 -0800

----------------------------------------------------------------------
 src/tests/container_logger_tests.cpp | 139 ++++++++++++++++++++++++++++++
 1 file changed, 139 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/0f20d5e7/src/tests/container_logger_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/container_logger_tests.cpp b/src/tests/container_logger_tests.cpp
index c6b2e59..0b1cbd8 100644
--- a/src/tests/container_logger_tests.cpp
+++ b/src/tests/container_logger_tests.cpp
@@ -22,12 +22,17 @@
 #include <process/future.hpp>
 #include <process/gtest.hpp>
 
+#include <stout/bytes.hpp>
 #include <stout/gtest.hpp>
 #include <stout/os.hpp>
 #include <stout/path.hpp>
 #include <stout/strings.hpp>
 #include <stout/try.hpp>
 
+#include <stout/os/exists.hpp>
+#include <stout/os/pstree.hpp>
+#include <stout/os/stat.hpp>
+
 #include "master/master.hpp"
 
 #include "slave/flags.hpp"
@@ -61,6 +66,10 @@ namespace mesos {
 namespace internal {
 namespace tests {
 
+const char LOGROTATE_CONTAINER_LOGGER_NAME[] =
+  "org_apache_mesos_LogrotateContainerLogger";
+
+
 class ContainerLoggerTest : public MesosTest {};
 
 
@@ -148,6 +157,136 @@ TEST_F(ContainerLoggerTest, DefaultToSandbox)
   Shutdown();
 }
 
+
+// Tests that the packaged logrotate container logger writes files into the
+// sandbox and keeps them at a reasonable size.
+TEST_F(ContainerLoggerTest, LOGROTATE_RotateInSandbox)
+{
+  // Create a master, agent, and framework.
+  Try<PID<Master>> master = StartMaster();
+  ASSERT_SOME(master);
+
+  Future<SlaveRegisteredMessage> slaveRegisteredMessage =
+    FUTURE_PROTOBUF(SlaveRegisteredMessage(), _, _);
+
+  // We'll need access to these flags later.
+  slave::Flags flags = CreateSlaveFlags();
+
+  // Use the non-default container logger that rotates logs.
+  flags.container_logger = LOGROTATE_CONTAINER_LOGGER_NAME;
+
+  Fetcher fetcher;
+
+  // We use an actual containerizer + executor since we want something to run.
+  Try<MesosContainerizer*> containerizer =
+    MesosContainerizer::create(flags, false, &fetcher);
+  CHECK_SOME(containerizer);
+
+  Try<PID<Slave>> slave = StartSlave(containerizer.get(), flags);
+  ASSERT_SOME(slave);
+
+  AWAIT_READY(slaveRegisteredMessage);
+  SlaveID slaveId = slaveRegisteredMessage.get().slave_id();
+
+  MockScheduler sched;
+  MesosSchedulerDriver driver(
+      &sched, DEFAULT_FRAMEWORK_INFO, master.get(), DEFAULT_CREDENTIAL);
+
+  Future<FrameworkID> frameworkId;
+  EXPECT_CALL(sched, registered(&driver, _, _))
+    .WillOnce(FutureArg<1>(&frameworkId));
+
+  // Wait for an offer, and start a task.
+  Future<vector<Offer>> offers;
+  EXPECT_CALL(sched, resourceOffers(&driver, _))
+    .WillOnce(FutureArg<1>(&offers))
+    .WillRepeatedly(Return()); // Ignore subsequent offers.
+
+  driver.start();
+  AWAIT_READY(frameworkId);
+
+  AWAIT_READY(offers);
+  EXPECT_NE(0u, offers.get().size());
+
+  // Start a task that spams stdout with 11 MB of (mostly blank) output.
+  // The logrotate container logger module is loaded with parameters that limit
+  // the log size to five files of 2 MB each.  After the task completes, there
+  // should be five files with a total size of 9 MB.  The first 2 MB file
+  // should have been deleted.  The "stdout" file should be 1 MB large.
+  TaskInfo task = createTask(
+      offers.get()[0],
+      "i=0; while [ $i -lt 11264 ]; "
+      "do printf '%-1024d\\n' $i; i=$((i+1)); done");
+
+  Future<TaskStatus> statusRunning;
+  Future<TaskStatus> statusFinished;
+  EXPECT_CALL(sched, statusUpdate(&driver, _))
+    .WillOnce(FutureArg<1>(&statusRunning))
+    .WillOnce(FutureArg<1>(&statusFinished))
+    .WillRepeatedly(Return());       // Ignore subsequent updates.
+
+  driver.launchTasks(offers.get()[0].id(), {task});
+
+  AWAIT_READY(statusRunning);
+  EXPECT_EQ(TASK_RUNNING, statusRunning.get().state());
+
+  AWAIT_READY(statusFinished);
+  EXPECT_EQ(TASK_FINISHED, statusFinished.get().state());
+
+  driver.stop();
+  driver.join();
+
+  Shutdown();
+
+  // The `LogrotateContainerLogger` spawns some `mesos-logrotate-logger`
+  // processes above, which continue running briefly after the container exits.
+  // Once they finish reading the container's pipe, they should exit.
+  Try<os::ProcessTree> pstrees = os::pstree(0);
+  ASSERT_SOME(pstrees);
+  foreach (const os::ProcessTree& pstree, pstrees.get().children) {
+    ASSERT_EQ(pstree.process.pid, waitpid(pstree.process.pid, NULL, 0));
+  }
+
+  // Check for the expected log rotation.
+  string sandboxDirectory = path::join(
+      slave::paths::getExecutorPath(
+          flags.work_dir,
+          slaveId,
+          frameworkId.get(),
+          statusRunning->executor_id()),
+      "runs",
+      "latest");
+
+  ASSERT_TRUE(os::exists(sandboxDirectory));
+
+  // The leading log file should be about half full (1 MB).
+  string stdoutPath = path::join(sandboxDirectory, "stdout");
+  ASSERT_TRUE(os::exists(stdoutPath));
+
+  // NOTE: We don't expect the size of the leading log file to be precisely
+  // one MB since there is also the executor's output besides the task's stdout.
+  Try<Bytes> stdoutSize = os::stat::size(stdoutPath);
+  ASSERT_SOME(stdoutSize);
+  EXPECT_LE(1024, stdoutSize->kilobytes());
+  EXPECT_GE(1050, stdoutSize->kilobytes());
+
+  // We should only have files up to "stdout.4".
+  stdoutPath = path::join(sandboxDirectory, "stdout.5");
+  EXPECT_FALSE(os::exists(stdoutPath));
+
+  // The next four rotated log files (2 MB each) should be present.
+  for (int i = 1; i < 5; i++) {
+    stdoutPath = path::join(sandboxDirectory, "stdout." + stringify(i));
+    ASSERT_TRUE(os::exists(stdoutPath));
+
+    // NOTE: The rotated files are written in contiguous blocks, meaning that
+    // each file may be less than the maximum allowed size.
+    stdoutSize = os::stat::size(stdoutPath);
+    EXPECT_LE(2040, stdoutSize->kilobytes());
+    EXPECT_GE(2048, stdoutSize->kilobytes());
+  }
+}
+
 } // namespace tests {
 } // namespace internal {
 } // namespace mesos {