You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by jo...@apache.org on 2016/07/25 23:36:46 UTC

[1/2] mesos git commit: Added example framework for testing disk quota enforcement.

Repository: mesos
Updated Branches:
  refs/heads/master 07a12a054 -> 0616b6b65


Added example framework for testing disk quota enforcement.

This adds an example framework which exercises the behavior of the agent
when the `--enforce_container_disk_quota` agent flag is enabled.
The framework will accept a fixed amount of disk, and launch a task
that will use a configurable amount of disk.  The framework reports
metrics about tasks failed due to disk limitation.

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


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

Branch: refs/heads/master
Commit: 5621284bdb7b3dcc5c87aae325664286673cdb9b
Parents: 07a12a0
Author: Artem Harutyunyan <ar...@mesosphere.io>
Authored: Mon Jul 25 15:47:21 2016 -0700
Committer: Joseph Wu <jo...@apache.org>
Committed: Mon Jul 25 16:11:30 2016 -0700

----------------------------------------------------------------------
 src/Makefile.am                      |   5 +
 src/examples/disk_full_framework.cpp | 473 ++++++++++++++++++++++++++++++
 2 files changed, 478 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/5621284b/src/Makefile.am
----------------------------------------------------------------------
diff --git a/src/Makefile.am b/src/Makefile.am
index cc83525..e8c63e9 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1895,6 +1895,11 @@ persistent_volume_framework_SOURCES = examples/persistent_volume_framework.cpp
 persistent_volume_framework_CPPFLAGS = $(MESOS_CPPFLAGS)
 persistent_volume_framework_LDADD = libmesos.la $(LDADD)
 
+check_PROGRAMS += disk-full-framework
+disk_full_framework_SOURCES = examples/disk_full_framework.cpp
+disk_full_framework_CPPFLAGS = $(MESOS_CPPFLAGS)
+disk_full_framework_LDADD = libmesos.la $(LDADD)
+
 if OS_LINUX
 check_PROGRAMS += setns-test-helper
 setns_test_helper_SOURCES =					\

http://git-wip-us.apache.org/repos/asf/mesos/blob/5621284b/src/examples/disk_full_framework.cpp
----------------------------------------------------------------------
diff --git a/src/examples/disk_full_framework.cpp b/src/examples/disk_full_framework.cpp
new file mode 100644
index 0000000..ad304fe
--- /dev/null
+++ b/src/examples/disk_full_framework.cpp
@@ -0,0 +1,473 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <glog/logging.h>
+
+#include <string>
+#include <vector>
+
+#include <mesos/resources.hpp>
+#include <mesos/scheduler.hpp>
+
+#include <process/clock.hpp>
+#include <process/defer.hpp>
+#include <process/http.hpp>
+#include <process/process.hpp>
+#include <process/protobuf.hpp>
+#include <process/time.hpp>
+
+#include <process/metrics/counter.hpp>
+#include <process/metrics/gauge.hpp>
+#include <process/metrics/metrics.hpp>
+
+#include <stout/bytes.hpp>
+#include <stout/duration.hpp>
+#include <stout/flags.hpp>
+#include <stout/option.hpp>
+#include <stout/os.hpp>
+#include <stout/try.hpp>
+
+
+using namespace mesos;
+
+using std::string;
+
+using process::Clock;
+using process::defer;
+
+using process::metrics::Gauge;
+using process::metrics::Counter;
+
+
+const double CPUS_PER_TASK = 0.1;
+const int MEMORY_PER_TASK = 16;
+const Bytes DISK_PER_TASK = Megabytes(5);
+
+
+class Flags : public flags::FlagsBase
+{
+public:
+  Flags()
+  {
+    add(&master,
+        "master",
+        "Master to connect to.");
+
+    add(&run_once,
+        "run_once",
+        "Whether this framework should exit after running a single task.\n"
+        "By default framework will keep running tasks forever.\n",
+        false);
+
+    add(&pre_sleep_duration,
+        "pre_sleep_duration",
+        "Duration of sleep before the task starts to consume the disk. The\n"
+        "purpose of this is to allow an operator to control the frequency at\n"
+        "which this framework consumes the available disk and terminates.\n"
+        "The task will sleep for the specified duration before ramping up\n"
+        "disk usage.\n",
+        Seconds(600));
+
+    add(&post_sleep_duration,
+        "post_sleep_duration",
+        "Duration of sleep after the task consumed the disk. The purpose\n"
+        "of this is to allow an operator to control how long it takes for\n"
+        "the task to terminate in case the disk quota enforcement does not\n"
+        "take effect. The task will terminate after sleeping for specified\n"
+        "duration.\n",
+        Seconds(600));
+
+    add(&disk_use_limit,
+        "disk_use_limit",
+        "The amount of disk (rounded to the nearest KB) the task should\n"
+        "consume. The task requests 5MB of disk, so if the limit is set\n"
+        "to exceed 5MB the expectation is that disk quota will be enforced\n"
+        "and the task will terminated.\n");
+  }
+
+  string master;
+  bool run_once;
+  Duration pre_sleep_duration;
+  Duration post_sleep_duration;
+  Bytes disk_use_limit;
+};
+
+// Actor holding the business logic and metrics for the `DiskFullScheduler`.
+// See `DiskFullScheduler` below for intended behavior.
+class DiskFullSchedulerProcess
+  : public process::Process<DiskFullSchedulerProcess>
+{
+public:
+  DiskFullSchedulerProcess (const Flags& _flags)
+    : flags(_flags),
+      tasksLaunched(0),
+      taskActive(false),
+      isRegistered(false),
+      metrics(*this)
+  {
+    start_time = Clock::now();
+  }
+
+  void registered()
+  {
+    isRegistered = true;
+  }
+
+  void disconnected()
+  {
+    isRegistered = false;
+  }
+
+  void resourceOffers(
+      SchedulerDriver* driver,
+      const std::vector<Offer>& offers)
+  {
+    static const Resources TASK_RESOURCES = Resources::parse(
+        "cpus:" + stringify(CPUS_PER_TASK) +
+        ";mem:" + stringify(MEMORY_PER_TASK) +
+        ";disk:" + stringify(DISK_PER_TASK.megabytes())).get();
+
+    foreach (const Offer& offer, offers) {
+      LOG(INFO) << "Received offer " << offer.id() << " from agent "
+                << offer.slave_id() << " (" << offer.hostname() << ") "
+                << "with " << offer.resources();
+
+      Resources resources(offer.resources());
+
+      // If we've already launched the task, or if the offer is not
+      // big enough, reject the offer.
+      if (taskActive || !resources.flatten().contains(TASK_RESOURCES)) {
+        Filters filters;
+        filters.set_refuse_seconds(600);
+
+        driver->declineOffer(offer.id(), filters);
+        continue;
+      }
+
+      int taskId = tasksLaunched++;
+
+      // The task sleeps for the amount of seconds specified by the
+      // pre_sleep_duration flag, ramps up the disk usage up to the limit
+      // specified by `--use_disk_limit` and then sleeps for
+      // post_sleep_duration more seconds.
+      static const string command =
+          "sleep " + stringify(flags.pre_sleep_duration.secs()) +
+          " && dd if=/dev/zero of=file bs=1K count=" +
+          stringify(flags.disk_use_limit.kilobytes()) +
+          " && sleep " + stringify(flags.post_sleep_duration.secs());
+
+      TaskInfo task;
+      task.set_name("Disk full framework task");
+      task.mutable_task_id()->set_value(stringify(taskId));
+      task.mutable_slave_id()->MergeFrom(offer.slave_id());
+      task.mutable_resources()->CopyFrom(TASK_RESOURCES);
+      task.mutable_command()->set_shell(true);
+      task.mutable_command()->set_value(command);
+
+      LOG(INFO) << "Starting task " << taskId;
+
+      driver->launchTasks(offer.id(), {task});
+
+      taskActive = true;
+    }
+  }
+
+  void statusUpdate(SchedulerDriver* driver, const TaskStatus& status)
+  {
+    if (stringify(tasksLaunched - 1) != status.task_id().value()) {
+      // We might receive messages from older tasks. Ignore them.
+      LOG(INFO) << "Ignoring status update from older task "
+                << status.task_id();
+      return;
+    }
+
+    switch (status.state()) {
+    case TASK_FINISHED:
+      if (flags.run_once) {
+          driver->stop();
+          break;
+      }
+
+      taskActive = false;
+      ++metrics.tasks_finished;
+      break;
+    case TASK_FAILED:
+      if (flags.run_once) {
+          driver->abort();
+          break;
+      }
+
+      taskActive = false;
+
+      if (status.reason() == TaskStatus::REASON_CONTAINER_LIMITATION_DISK) {
+        ++metrics.tasks_disk_full;
+
+        // Increment abnormal_termination metric counter in case the task
+        // wasn't supposed to consume beyond its disk quota but still got
+        // terminated because of disk overuse.
+        if (flags.disk_use_limit >= DISK_PER_TASK) {
+          ++metrics.abnormal_terminations;
+        }
+
+        break;
+      }
+
+      ++metrics.abnormal_terminations;
+      break;
+    case TASK_KILLED:
+    case TASK_LOST:
+    case TASK_ERROR:
+      if (flags.run_once) {
+        driver->abort();
+      }
+
+      taskActive = false;
+      ++metrics.abnormal_terminations;
+      break;
+    case TASK_STARTING:
+    case TASK_RUNNING:
+    case TASK_STAGING:
+    case TASK_KILLING:
+      break;
+    }
+  }
+
+private:
+  const Flags flags;
+  int tasksLaunched;
+  bool taskActive;
+
+  process::Time start_time;
+
+  double _uptime_secs()
+  {
+    return (Clock::now() - start_time).secs();
+  }
+
+  bool isRegistered;
+  double _registered()
+  {
+    return isRegistered ? 1 : 0;
+  }
+
+  struct Metrics
+  {
+    Metrics(const DiskFullSchedulerProcess& _scheduler)
+      : uptime_secs(
+            "disk_full_framework/uptime_secs",
+            defer(_scheduler, &DiskFullSchedulerProcess::_uptime_secs)),
+        registered(
+            "disk_full_framework/registered",
+            defer(_scheduler, &DiskFullSchedulerProcess::_registered)),
+        tasks_finished("disk_full_framework/tasks_finished"),
+        tasks_disk_full("disk_full_framework/tasks_disk_full"),
+        abnormal_terminations("disk_full_framework/abnormal_terminations")
+    {
+      process::metrics::add(uptime_secs);
+      process::metrics::add(registered);
+      process::metrics::add(tasks_finished);
+      process::metrics::add(tasks_disk_full);
+      process::metrics::add(abnormal_terminations);
+    }
+
+    ~Metrics()
+    {
+      process::metrics::remove(uptime_secs);
+      process::metrics::remove(registered);
+      process::metrics::remove(tasks_finished);
+      process::metrics::remove(tasks_disk_full);
+      process::metrics::remove(abnormal_terminations);
+    }
+
+    process::metrics::Gauge uptime_secs;
+    process::metrics::Gauge registered;
+
+    process::metrics::Counter tasks_finished;
+    process::metrics::Counter tasks_disk_full;
+    process::metrics::Counter abnormal_terminations;
+  } metrics;
+};
+
+
+// This scheduler starts a task which gradually consumes the disk until it
+// reaches the limit. The framework expects the disk quota to be enforced
+// and the task to be killed.
+class DiskFullScheduler : public Scheduler
+{
+public:
+  DiskFullScheduler(const Flags& _flags)
+    : process(_flags)
+  {
+    process::spawn(process);
+  }
+
+  virtual ~DiskFullScheduler()
+  {
+    process::terminate(process);
+    process::wait(process);
+  }
+
+  virtual void registered(
+      SchedulerDriver*,
+      const FrameworkID& frameworkId,
+      const MasterInfo&)
+  {
+    LOG(INFO) << "Registered with framework ID: " << frameworkId;
+
+    process::dispatch(&process, &DiskFullSchedulerProcess::registered);
+  }
+
+  virtual void reregistered(SchedulerDriver*, const MasterInfo&)
+  {
+    LOG(INFO) << "Reregistered";
+
+    process::dispatch(&process, &DiskFullSchedulerProcess::registered);
+  }
+
+  virtual void disconnected(SchedulerDriver*)
+  {
+    LOG(INFO) << "Disconnected";
+
+    process::dispatch(
+        &process,
+        &DiskFullSchedulerProcess::disconnected);
+  }
+
+  virtual void resourceOffers(
+      SchedulerDriver* driver,
+      const std::vector<Offer>& offers)
+  {
+    LOG(INFO) << "Resource offers received";
+
+    process::dispatch(
+         &process,
+         &DiskFullSchedulerProcess::resourceOffers,
+         driver,
+         offers);
+  }
+
+  virtual void offerRescinded(SchedulerDriver*, const OfferID&)
+  {
+    LOG(INFO) << "Offer rescinded";
+  }
+
+  virtual void statusUpdate(SchedulerDriver* driver, const TaskStatus& status)
+  {
+    LOG(INFO) << "Task " << status.task_id() << " in state "
+              << TaskState_Name(status.state())
+              << ", Source: " << status.source()
+              << ", Reason: " << status.reason()
+              << (status.has_message() ? ", Message: " + status.message() : "");
+
+    process::dispatch(
+        &process,
+        &DiskFullSchedulerProcess::statusUpdate,
+        driver,
+        status);
+  }
+
+  virtual void frameworkMessage(
+      SchedulerDriver*,
+      const ExecutorID&,
+      const SlaveID&,
+      const string& data)
+  {
+    LOG(INFO) << "Framework message: " << data;
+  }
+
+  virtual void slaveLost(SchedulerDriver*, const SlaveID& slaveId)
+  {
+    LOG(INFO) << "Agent lost: " << slaveId;
+  }
+
+  virtual void executorLost(
+      SchedulerDriver*,
+      const ExecutorID& executorId,
+      const SlaveID& slaveId,
+      int)
+  {
+    LOG(INFO) << "Executor '" << executorId << "' lost on agent: " << slaveId;
+  }
+
+  virtual void error(SchedulerDriver*, const string& message)
+  {
+    LOG(INFO) << "Error message: " << message;
+  }
+
+private:
+  DiskFullSchedulerProcess process;
+};
+
+
+int main(int argc, char** argv)
+{
+  Flags flags;
+  Try<flags::Warnings> load = flags.load("MESOS_", argc, argv);
+
+  if (load.isError()) {
+    EXIT(EXIT_FAILURE) << flags.usage(load.error());
+  }
+
+  DiskFullScheduler scheduler(flags);
+
+  FrameworkInfo framework;
+  framework.set_user(""); // Have Mesos fill the current user.
+  framework.set_name("Disk Full Framework (C++)");
+  framework.set_checkpoint(true);
+
+  MesosSchedulerDriver* driver;
+
+  // TODO(hartem): Refactor these into a common set of flags.
+  Option<string> value = os::getenv("MESOS_AUTHENTICATE_FRAMEWORKS");
+  if (value.isSome()) {
+    LOG(INFO) << "Enabling authentication for the framework";
+
+    value = os::getenv("DEFAULT_PRINCIPAL");
+    if (value.isNone()) {
+      EXIT(EXIT_FAILURE)
+        << "Expecting authentication principal in the environment";
+    }
+
+    Credential credential;
+    credential.set_principal(value.get());
+
+    framework.set_principal(value.get());
+
+    value = os::getenv("DEFAULT_SECRET");
+    if (value.isNone()) {
+      EXIT(EXIT_FAILURE)
+        << "Expecting authentication secret in the environment";
+    }
+
+    credential.set_secret(value.get());
+
+    driver = new MesosSchedulerDriver(
+        &scheduler, framework, flags.master, credential);
+  } else {
+    framework.set_principal("disk-full-framework-cpp");
+
+    driver = new MesosSchedulerDriver(
+        &scheduler, framework, flags.master);
+  }
+
+  int status = driver->run() == DRIVER_STOPPED ? 0 : 1;
+
+  // Ensure that the driver process terminates.
+  driver->stop();
+
+  delete driver;
+  return status;
+}


[2/2] mesos git commit: Added disk full framework to example framework tests.

Posted by jo...@apache.org.
Added disk full framework to example framework tests.

This test is roughly equivalent to the existing
`DiskQuotaTest.DiskUsageExceedsQuota` test.

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


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

Branch: refs/heads/master
Commit: 0616b6b65ebe7bbf14092b8f4445481797ebb40f
Parents: 5621284
Author: Artem Harutyunyan <ar...@mesosphere.io>
Authored: Mon Jul 25 16:13:58 2016 -0700
Committer: Joseph Wu <jo...@apache.org>
Committed: Mon Jul 25 16:32:14 2016 -0700

----------------------------------------------------------------------
 src/Makefile.am                       |   6 +-
 src/tests/disk_full_framework_test.sh | 104 +++++++++++++++++++++++++++++
 src/tests/examples_tests.cpp          |   3 +
 3 files changed, 111 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/0616b6b6/src/Makefile.am
----------------------------------------------------------------------
diff --git a/src/Makefile.am b/src/Makefile.am
index e8c63e9..3d33ee7 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -2247,14 +2247,15 @@ EXTRA_DIST +=							\
 
 dist_check_SCRIPTS +=						\
   tests/balloon_framework_test.sh				\
+  tests/disk_full_framework_test.sh				\
   tests/dynamic_reservation_framework_test.sh			\
-  tests/test_http_framework_test.sh				\
   tests/java_exception_test.sh					\
   tests/java_framework_test.sh					\
   tests/java_log_test.sh					\
   tests/no_executor_framework_test.sh				\
   tests/persistent_volume_framework_test.sh			\
   tests/python_framework_test.sh				\
+  tests/test_http_framework_test.sh				\
   tests/test_framework_test.sh
 
 ../3rdparty/libgmock.la:
@@ -2264,13 +2265,14 @@ if INSTALL_TESTS
 testlibexec_PROGRAMS = $(check_PROGRAMS)
 dist_testlibexec_SCRIPTS =			\
   tests/balloon_framework_test.sh		\
-  tests/test_http_framework_test.sh		\
+  tests/disk_full_framework_test.sh		\
   tests/java_exception_test.sh			\
   tests/java_framework_test.sh			\
   tests/java_log_test.sh			\
   tests/no_executor_framework_test.sh		\
   tests/persistent_volume_framework_test.sh	\
   tests/python_framework_test.sh		\
+  tests/test_http_framework_test.sh		\
   tests/test_framework_test.sh
 
 endif

http://git-wip-us.apache.org/repos/asf/mesos/blob/0616b6b6/src/tests/disk_full_framework_test.sh
----------------------------------------------------------------------
diff --git a/src/tests/disk_full_framework_test.sh b/src/tests/disk_full_framework_test.sh
new file mode 100755
index 0000000..3fc180b
--- /dev/null
+++ b/src/tests/disk_full_framework_test.sh
@@ -0,0 +1,104 @@
+#!/usr/bin/env bash
+
+# This script runs the disk full framework on a cluster using the disk/du
+# isolator and checks that the framework returns a status of 1.
+
+source ${MESOS_SOURCE_DIR}/support/colors.sh
+source ${MESOS_SOURCE_DIR}/support/atexit.sh
+source ${MESOS_HELPER_DIR}/colors.sh
+source ${MESOS_HELPER_DIR}/atexit.sh
+
+MASTER_PID=
+AGENT_PID=
+MESOS_WORK_DIR=`mktemp -d -t mesos-XXXXXX`
+
+function cleanup() {
+  # Make sure we kill the master on exit.
+  if [[ ! -z ${MASTER_PID} ]]; then
+    kill ${MASTER_PID}
+  fi
+
+  # Make sure we kill the agent on exit.
+  if [[ ! -z ${AGENT_PID} ]]; then
+    kill ${AGENT_PID}
+  fi
+
+  if [[ -d "${MESOS_WORK_DIR}" ]]; then
+    rm -rf ${MESOS_WORK_DIR};
+  fi
+}
+
+atexit cleanup
+
+export LD_LIBRARY_PATH=${MESOS_BUILD_DIR}/src/.libs
+MASTER=${MESOS_SBIN_DIR}/mesos-master
+AGENT=${MESOS_SBIN_DIR}/mesos-agent
+DISK_FULL_FRAMEWORK=${MESOS_HELPER_DIR}/disk-full-framework
+
+# The mesos binaries expect MESOS_ prefixed environment variables
+# to correspond to flags, so we unset these here.
+unset MESOS_BUILD_DIR
+unset MESOS_SOURCE_DIR
+unset MESOS_HELPER_DIR
+unset MESOS_VERBOSE
+
+# Launch master.
+${MASTER} \
+    --ip=127.0.0.1 \
+    --port=5432 \
+    --work_dir=${MESOS_WORK_DIR} &
+MASTER_PID=${!}
+echo "${GREEN}Launched master at ${MASTER_PID}${NORMAL}"
+sleep 2
+
+# Check the master is still running after 2 seconds.
+kill -0 ${MASTER_PID} >/dev/null 2>&1
+STATUS=${?}
+if [[ ${STATUS} -ne 0 ]]; then
+  echo "{RED}Master crashed; failing test${NORMAL}"
+  exit 2
+fi
+
+# Launch agent.
+${AGENT} \
+    --work_dir=${MESOS_WORK_DIR} \
+    --master=127.0.0.1:5432 \
+    --isolation='disk/du' \
+    --enforce_container_disk_quota \
+    --resources="cpus:1;mem:96;disk:50" &
+AGENT_PID=${!}
+echo "${GREEN}Launched agent at ${AGENT_PID}${NORMAL}"
+sleep 2
+
+# Check the agent is still running after 2 seconds.
+kill -0 ${AGENT_PID} >/dev/null 2>&1
+STATUS=${?}
+if [[ ${STATUS} -ne 0 ]]; then
+  echo "${RED}Slave crashed; failing test${NORMAL}"
+  exit 2
+fi
+
+# The main event!
+${DISK_FULL_FRAMEWORK} \
+    --master=127.0.0.1:5432 \
+    --pre_sleep_duration=1secs \
+    --post_sleep_duration=30secs \
+    --disk_use_limit=10mb \
+    --run_once
+STATUS=${?}
+
+# Make sure the disk full framework "failed".
+if [[ ! ${STATUS} -eq 1 ]]; then
+  echo "${RED} Disk full framework returned ${STATUS} not 1${NORMAL}"
+  exit 1
+fi
+
+# And make sure the agent is still running!
+kill -0 ${AGENT_PID} >/dev/null 2>&1
+STATUS=${?}
+if [[ ${STATUS} -ne 0 ]]; then
+  echo "${RED}Slave crashed; failing test${NORMAL}"
+  exit 2
+fi
+
+exit 0

http://git-wip-us.apache.org/repos/asf/mesos/blob/0616b6b6/src/tests/examples_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/examples_tests.cpp b/src/tests/examples_tests.cpp
index ac513ce..cac5304 100644
--- a/src/tests/examples_tests.cpp
+++ b/src/tests/examples_tests.cpp
@@ -31,6 +31,9 @@ TEST_SCRIPT(ExamplesTest, PersistentVolumeFramework,
 TEST_SCRIPT(ExamplesTest, DynamicReservationFramework,
             "dynamic_reservation_framework_test.sh")
 
+TEST_SCRIPT(ExamplesTest, DiskFullFramework,
+            "disk_full_framework_test.sh")
+
 #ifdef MESOS_HAS_JAVA
 TEST_SCRIPT(ExamplesTest, JavaFramework, "java_framework_test.sh")
 TEST_SCRIPT(ExamplesTest, JavaException, "java_exception_test.sh")