inline TaskInfo createTask( const Offer& offer, const std::string& command, const Option<mesos::ExecutorID>& executorId = None(), const std::string& name = "test-task", const std::string& id = UUID::random().toString()) { return createTask( offer.slave_id(), offer.resources(), command, executorId, name, id); }
// TODO(benh): Move this into utils, make more generic, and use in // other tests. vector<TaskInfo> createTasks(const Offer& offer) { TaskInfo task; task.set_name("test-task"); task.mutable_task_id()->set_value("1"); task.mutable_slave_id()->MergeFrom(offer.slave_id()); task.mutable_resources()->MergeFrom(offer.resources()); task.mutable_executor()->MergeFrom(DEFAULT_EXECUTOR_INFO); vector<TaskInfo> tasks; tasks.push_back(task); return tasks; }
inline double getScalarResource(const Offer& offer, const std::string& name) { double value = 0.0; for (int i = 0; i < offer.resources_size(); i++) { const Resource& resource = offer.resources(i); if (resource.name() == name && resource.type() == Value::SCALAR) { value = resource.scalar().value(); } } return value; }
inline TaskInfo createTask( const Offer& offer, const std::string& command, const std::string& name = "test-task", const std::string& id = UUID::random().toString()) { TaskInfo task; task.set_name(name); task.mutable_task_id()->set_value(id); task.mutable_slave_id()->MergeFrom(offer.slave_id()); task.mutable_resources()->MergeFrom(offer.resources()); task.mutable_command()->set_value(command); return task; }
inline TaskInfo createTask( const Offer& offer, const std::string& command, const Option<mesos::ExecutorID>& executorId = None(), const std::string& name = "test-task", const std::string& id = UUID::random().toString()) { TaskInfo task; task.set_name(name); task.mutable_task_id()->set_value(id); task.mutable_slave_id()->CopyFrom(offer.slave_id()); task.mutable_resources()->CopyFrom(offer.resources()); if (executorId.isSome()) { ExecutorInfo executor; executor.mutable_executor_id()->CopyFrom(executorId.get()); executor.mutable_command()->set_value(command); task.mutable_executor()->CopyFrom(executor); } else { task.mutable_command()->set_value(command); } return task; }
vector<TaskInfo> populateTasks( const string& cmd, CommandInfo healthCommand, const Offer& offer, int gracePeriodSeconds = 0, const Option<int>& consecutiveFailures = None(), const Option<map<string, string> >& env = None()) { TaskInfo task; task.set_name(""); task.mutable_task_id()->set_value("1"); task.mutable_slave_id()->CopyFrom(offer.slave_id()); task.mutable_resources()->CopyFrom(offer.resources()); CommandInfo command; command.set_value(cmd); Environment::Variable* variable = command.mutable_environment()->add_variables(); // We need to set the correct directory to launch health check process // instead of the default for tests. variable->set_name("MESOS_LAUNCHER_DIR"); variable->set_value(path::join(tests::flags.build_dir, "src")); task.mutable_command()->CopyFrom(command); HealthCheck healthCheck; if (env.isSome()) { foreachpair (const string& name, const string value, env.get()) { Environment::Variable* variable = healthCommand.mutable_environment()->mutable_variables()->Add(); variable->set_name(name); variable->set_value(value); } }
TEST_F(FaultToleranceTest, ForwardStatusUpdateUnknownExecutor) { Try<PID<Master> > master = StartMaster(); ASSERT_SOME(master); MockExecutor exec(DEFAULT_EXECUTOR_ID); Try<PID<Slave> > slave = StartSlave(&exec); ASSERT_SOME(slave); MockScheduler sched; MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master.get()); FrameworkID frameworkId; EXPECT_CALL(sched, registered(&driver, _, _)) .WillOnce(SaveArg<1>(&frameworkId)); Future<vector<Offer> > offers; EXPECT_CALL(sched, resourceOffers(&driver, _)) .WillOnce(FutureArg<1>(&offers)); driver.start(); AWAIT_READY(offers); EXPECT_NE(0u, offers.get().size()); Offer offer = offers.get()[0]; TaskInfo task; task.set_name(""); task.mutable_task_id()->set_value("1"); task.mutable_slave_id()->MergeFrom(offer.slave_id()); task.mutable_resources()->MergeFrom(offer.resources()); task.mutable_executor()->MergeFrom(DEFAULT_EXECUTOR_INFO); vector<TaskInfo> tasks; tasks.push_back(task); Future<Nothing> statusUpdate; EXPECT_CALL(sched, statusUpdate(&driver, _)) .WillOnce(FutureSatisfy(&statusUpdate)); // TASK_RUNNING of task1. EXPECT_CALL(exec, registered(_, _, _, _)); EXPECT_CALL(exec, launchTask(_, _)) .WillOnce(SendStatusUpdateFromTask(TASK_RUNNING)); driver.launchTasks(offer.id(), tasks); // Wait until TASK_RUNNING of task1 is received. AWAIT_READY(statusUpdate); // Simulate the slave receiving status update from an unknown // (e.g. exited) executor of the given framework. Future<TaskStatus> status; EXPECT_CALL(sched, statusUpdate(&driver, _)) .WillOnce(FutureArg<1>(&status)); // TASK_RUNNING of task2. TaskID taskId; taskId.set_value("task2"); StatusUpdate statusUpdate2 = createStatusUpdate( frameworkId, offer.slave_id(), taskId, TASK_RUNNING, "Dummy update"); process::dispatch(slave.get(), &Slave::statusUpdate, statusUpdate2); // Ensure that the scheduler receives task2's update. AWAIT_READY(status); EXPECT_EQ(taskId, status.get().task_id()); EXPECT_EQ(TASK_RUNNING, status.get().state()); EXPECT_CALL(exec, shutdown(_)) .Times(AtMost(1)); driver.stop(); driver.join(); Shutdown(); }