src/tests/slave_tests.cpp
TEST_F(SlaveTest, TerminalTaskContainerizerUpdateFails)
{
  // Start a master.
  Try<Owned<cluster::Master>> master = StartMaster();
  ASSERT_SOME(master);

  MockExecutor exec(DEFAULT_EXECUTOR_ID);
  TestContainerizer containerizer(&exec);
  EXPECT_CALL(exec, registered(_, _, _, _));

  Owned<MasterDetector> detector = master.get()->createDetector();

  // Start a slave.
  Try<Owned<cluster::Slave>> slave = StartSlave(detector.get(), &containerizer);
  ASSERT_SOME(slave);

  MockScheduler sched;
  MesosSchedulerDriver driver(
      &sched, DEFAULT_FRAMEWORK_INFO, master.get()->pid, DEFAULT_CREDENTIAL);

  EXPECT_CALL(sched, registered(_, _, _));

  Future<vector<Offer>> offers;

  EXPECT_CALL(sched, resourceOffers(&driver, _))
    .WillOnce(FutureArg<1>(&offers))
    .WillRepeatedly(Return()); // Ignore subsequent offers.

  driver.start();

  AWAIT_READY(offers);
  EXPECT_NE(0u, offers.get().size());
  Offer offer = offers.get()[0];

  // Start two tasks.
  vector<TaskInfo> tasks;

  tasks.push_back(createTask(
      offer.slave_id(),
      Resources::parse("cpus:0.1;mem:32").get(),
      "sleep 1000",
      exec.id));

  tasks.push_back(createTask(
      offer.slave_id(),
      Resources::parse("cpus:0.1;mem:32").get(),
      "sleep 1000",
      exec.id));

  EXPECT_CALL(exec, launchTask(_, _))
    .WillOnce(SendStatusUpdateFromTask(TASK_RUNNING))
    .WillOnce(SendStatusUpdateFromTask(TASK_RUNNING));

  Future<TaskStatus> status1, status2, status3, status4;
  EXPECT_CALL(sched, statusUpdate(&driver, _))
    .WillOnce(FutureArg<1>(&status1))
    .WillOnce(FutureArg<1>(&status2))
    .WillOnce(FutureArg<1>(&status3))
    .WillOnce(FutureArg<1>(&status4));

  driver.launchTasks(offer.id(), tasks);

  AWAIT_READY(status1);
  EXPECT_EQ(TASK_RUNNING, status1.get().state());

  AWAIT_READY(status2);
  EXPECT_EQ(TASK_RUNNING, status2.get().state());

  // Set up the containerizer so the next update() will fail.
  EXPECT_CALL(containerizer, update(_, _))
    .WillOnce(Return(Failure("update() failed")))
    .WillRepeatedly(Return(Nothing()));

  EXPECT_CALL(exec, killTask(_, _))
    .WillOnce(SendStatusUpdateFromTaskID(TASK_KILLED));

  Future<Nothing> executorLost;
  EXPECT_CALL(sched, executorLost(&driver, DEFAULT_EXECUTOR_ID, _, _))
    .WillOnce(FutureSatisfy(&executorLost));

  // Kill one of the tasks. The failed update should result in the
  // second task going lost when the container is destroyed.
  driver.killTask(tasks[0].task_id());

  AWAIT_READY(status3);
  EXPECT_EQ(TASK_KILLED, status3.get().state());
  EXPECT_EQ(TaskStatus::SOURCE_EXECUTOR, status3.get().source());

  AWAIT_READY(status4);
  EXPECT_EQ(TASK_LOST, status4->state());
  EXPECT_EQ(TaskStatus::SOURCE_SLAVE, status4->source());
  EXPECT_EQ(TaskStatus::REASON_CONTAINER_UPDATE_FAILED, status4->reason());

  AWAIT_READY(executorLost);

  driver.stop();
  driver.join();
}
// This test verifies the slave will destroy a container if, when
// receiving a terminal status task update, updating the container's
// resources fails.
This test verifies the slave will destroy a container if, when
receiving a terminal status task update, updating the container's
resources fails.
This test verifies the slave will destroy a container if when receiving a terminal status task update updating the container ' s resources fails .
TEST_F(SlaveTest, TerminalTaskContainerizerUpdateFails)
{
  Try<Owned<cluster::Master>> master = StartMaster();
  ASSERT_SOME(master);
  MockExecutor exec(DEFAULT_EXECUTOR_ID);
  TestContainerizer containerizer(&exec);
  EXPECT_CALL(exec, registered(_, _, _, _));
  Owned<MasterDetector> detector = master.get()->createDetector();
  Try<Owned<cluster::Slave>> slave = StartSlave(detector.get(), &containerizer);
  ASSERT_SOME(slave);
  MockScheduler sched;
  MesosSchedulerDriver driver(
      &sched, DEFAULT_FRAMEWORK_INFO, master.get()->pid, DEFAULT_CREDENTIAL);
  EXPECT_CALL(sched, registered(_, _, _));
  Future<vector<Offer>> offers;
  EXPECT_CALL(sched, resourceOffers(&driver, _))
    .WillOnce(FutureArg<1>(&offers))
    .WillRepeatedly(Return()); 
  driver.start();
  AWAIT_READY(offers);
  EXPECT_NE(0u, offers.get().size());
  Offer offer = offers.get()[0];
  vector<TaskInfo> tasks;
  tasks.push_back(createTask(
      offer.slave_id(),
      Resources::parse("cpus:0.1;mem:32").get(),
      "sleep 1000",
      exec.id));
  tasks.push_back(createTask(
      offer.slave_id(),
      Resources::parse("cpus:0.1;mem:32").get(),
      "sleep 1000",
      exec.id));
  EXPECT_CALL(exec, launchTask(_, _))
    .WillOnce(SendStatusUpdateFromTask(TASK_RUNNING))
    .WillOnce(SendStatusUpdateFromTask(TASK_RUNNING));
  Future<TaskStatus> status1, status2, status3, status4;
  EXPECT_CALL(sched, statusUpdate(&driver, _))
    .WillOnce(FutureArg<1>(&status1))
    .WillOnce(FutureArg<1>(&status2))
    .WillOnce(FutureArg<1>(&status3))
    .WillOnce(FutureArg<1>(&status4));
  driver.launchTasks(offer.id(), tasks);
  AWAIT_READY(status1);
  EXPECT_EQ(TASK_RUNNING, status1.get().state());
  AWAIT_READY(status2);
  EXPECT_EQ(TASK_RUNNING, status2.get().state());
  EXPECT_CALL(containerizer, update(_, _))
    .WillOnce(Return(Failure("update() failed")))
    .WillRepeatedly(Return(Nothing()));
  EXPECT_CALL(exec, killTask(_, _))
    .WillOnce(SendStatusUpdateFromTaskID(TASK_KILLED));
  Future<Nothing> executorLost;
  EXPECT_CALL(sched, executorLost(&driver, DEFAULT_EXECUTOR_ID, _, _))
    .WillOnce(FutureSatisfy(&executorLost));
  driver.killTask(tasks[0].task_id());
  AWAIT_READY(status3);
  EXPECT_EQ(TASK_KILLED, status3.get().state());
  EXPECT_EQ(TaskStatus::SOURCE_EXECUTOR, status3.get().source());
  AWAIT_READY(status4);
  EXPECT_EQ(TASK_LOST, status4->state());
  EXPECT_EQ(TaskStatus::SOURCE_SLAVE, status4->source());
  EXPECT_EQ(TaskStatus::REASON_CONTAINER_UPDATE_FAILED, status4->reason());
  AWAIT_READY(executorLost);
  driver.stop();
  driver.join();
}
TEST_F ( SlaveTest , TerminalTaskContainerizerUpdateFails ) { Try < Owned < cluster :: Master > > master = StartMaster ( ) ; ASSERT_SOME ( master ) ; MockExecutor exec ( DEFAULT_EXECUTOR_ID ) ; TestContainerizer containerizer ( & exec ) ; EXPECT_CALL ( exec , registered ( _ , _ , _ , _ ) ) ; Owned < MasterDetector > detector = master . get ( ) -> createDetector ( ) ; Try < Owned < cluster :: Slave > > slave = StartSlave ( detector . get ( ) , & containerizer ) ; ASSERT_SOME ( slave ) ; MockScheduler sched ; MesosSchedulerDriver driver ( & sched , DEFAULT_FRAMEWORK_INFO , master . get ( ) -> pid , DEFAULT_CREDENTIAL ) ; EXPECT_CALL ( sched , registered ( _ , _ , _ ) ) ; Future < vector < Offer > > offers ; EXPECT_CALL ( sched , resourceOffers ( & driver , _ ) ) . WillOnce ( FutureArg < 1 > ( & offers ) ) . WillRepeatedly ( Return ( ) ) ; driver . start ( ) ; AWAIT_READY ( offers ) ; EXPECT_NE ( 0u , offers . get ( ) . size ( ) ) ; Offer offer = offers . get ( ) [ 0 ] ; vector < TaskInfo > tasks ; tasks . push_back ( createTask ( offer . slave_id ( ) , Resources :: parse ( " " ) . get ( ) , " " , exec . id ) ) ; tasks . push_back ( createTask ( offer . slave_id ( ) , Resources :: parse ( " " ) . get ( ) , " " , exec . id ) ) ; EXPECT_CALL ( exec , launchTask ( _ , _ ) ) . WillOnce ( SendStatusUpdateFromTask ( TASK_RUNNING ) ) . WillOnce ( SendStatusUpdateFromTask ( TASK_RUNNING ) ) ; Future < TaskStatus > status1 , status2 , status3 , status4 ; EXPECT_CALL ( sched , statusUpdate ( & driver , _ ) ) . WillOnce ( FutureArg < 1 > ( & status1 ) ) . WillOnce ( FutureArg < 1 > ( & status2 ) ) . WillOnce ( FutureArg < 1 > ( & status3 ) ) . WillOnce ( FutureArg < 1 > ( & status4 ) ) ; driver . launchTasks ( offer . id ( ) , tasks ) ; AWAIT_READY ( status1 ) ; EXPECT_EQ ( TASK_RUNNING , status1 . get ( ) . state ( ) ) ; AWAIT_READY ( status2 ) ; EXPECT_EQ ( TASK_RUNNING , status2 . get ( ) . state ( ) ) ; EXPECT_CALL ( containerizer , update ( _ , _ ) ) . WillOnce ( Return ( Failure ( " " ) ) ) . WillRepeatedly ( Return ( Nothing ( ) ) ) ; EXPECT_CALL ( exec , killTask ( _ , _ ) ) . WillOnce ( SendStatusUpdateFromTaskID ( TASK_KILLED ) ) ; Future < Nothing > executorLost ; EXPECT_CALL ( sched , executorLost ( & driver , DEFAULT_EXECUTOR_ID , _ , _ ) ) . WillOnce ( FutureSatisfy ( & executorLost ) ) ; driver . killTask ( tasks [ 0 ] . task_id ( ) ) ; AWAIT_READY ( status3 ) ; EXPECT_EQ ( TASK_KILLED , status3 . get ( ) . state ( ) ) ; EXPECT_EQ ( TaskStatus :: SOURCE_EXECUTOR , status3 . get ( ) . source ( ) ) ; AWAIT_READY ( status4 ) ; EXPECT_EQ ( TASK_LOST , status4 -> state ( ) ) ; EXPECT_EQ ( TaskStatus :: SOURCE_SLAVE , status4 -> source ( ) ) ; EXPECT_EQ ( TaskStatus :: REASON_CONTAINER_UPDATE_FAILED , status4 -> reason ( ) ) ; AWAIT_READY ( executorLost ) ; driver . stop ( ) ; driver . join ( ) ; }
This test verifies the slave will destroy a container if, when
receiving a terminal status task update, updating the container's
resources fails.
This test verifies the slave will destroy a container if when receiving a terminal status task update updating the container ' s resources fails .
// Start a master. // Start a slave. // Ignore subsequent offers. // Start two tasks. // Set up the containerizer so the next update() will fail. // Kill one of the tasks. The failed update should result in the // second task going lost when the container is destroyed.