private TaskInfo makeTaskInfo(IScheduledTask task) { return TaskInfo.newBuilder() .setName(Tasks.id(task)) .setTaskId(TaskID.newBuilder().setValue(Tasks.id(task))) .setSlaveId(SlaveID.newBuilder().setValue("slave-id" + task.toString())) .build(); }
@Test public void testStorageException() { IScheduledTask task = makeTask("a", PENDING); TaskInfo mesosTask = TaskInfo.newBuilder() .setName(Tasks.id(task)) .setTaskId(TaskID.newBuilder().setValue(Tasks.id(task))) .setSlaveId(SlaveID.newBuilder().setValue("slaveId")) .build(); Capture<Runnable> timeoutCapture = expectTaskGroupBackoff(10); expectAnyMaintenanceCalls(); expectOfferDeclineIn(10); expect(assigner.maybeAssign(OFFER_A, task)).andThrow(new StorageException("Injected failure.")); Capture<Runnable> timeoutCapture2 = expectTaskGroupBackoff(10, 20); expect(preemptor.findPreemptionSlotFor("a")).andReturn(Optional.<String>absent()); expect(assigner.maybeAssign(OFFER_A, task)).andReturn(Optional.of(mesosTask)); driver.launchTask(OFFER_A.getId(), mesosTask); expectLastCall(); replayAndCreateScheduler(); changeState(task, INIT, PENDING); offerQueue.addOffer(OFFER_A); timeoutCapture.getValue().run(); timeoutCapture2.getValue().run(); }
@Test public void testDriverNotReady() { IScheduledTask task = makeTask("a", PENDING); TaskInfo mesosTask = TaskInfo.newBuilder() .setName(Tasks.id(task)) .setTaskId(TaskID.newBuilder().setValue(Tasks.id(task))) .setSlaveId(SlaveID.newBuilder().setValue("slaveId")) .build(); Capture<Runnable> timeoutCapture = expectTaskGroupBackoff(10); expectAnyMaintenanceCalls(); expectOfferDeclineIn(10); expect(assigner.maybeAssign(OFFER_A, task)).andReturn(Optional.of(mesosTask)); driver.launchTask(OFFER_A.getId(), mesosTask); expectLastCall().andThrow(new IllegalStateException("Driver not ready.")); expect( stateManager.changeState( Query.taskScoped("a").byStatus(PENDING), LOST, TaskScheduler.LAUNCH_FAILED_MSG)) .andReturn(1); replayAndCreateScheduler(); changeState(task, INIT, PENDING); offerQueue.addOffer(OFFER_A); timeoutCapture.getValue().run(); }
@Test public void testDontDeclineAcceptedOffer() throws OfferQueue.LaunchException { expectAnyMaintenanceCalls(); Capture<Runnable> offerExpirationCapture = expectOfferDeclineIn(10); Function<Offer, Optional<TaskInfo>> offerAcceptor = createMock(new Clazz<Function<Offer, Optional<TaskInfo>>>() {}); final TaskInfo taskInfo = TaskInfo.getDefaultInstance(); expect(offerAcceptor.apply(OFFER_A)).andReturn(Optional.of(taskInfo)); driver.launchTask(OFFER_A.getId(), taskInfo); replayAndCreateScheduler(); offerQueue.addOffer(OFFER_A); offerQueue.launchFirst(offerAcceptor); offerExpirationCapture.getValue().run(); }
public class TaskAssignerImplTest extends EasyMockTest { private static final int PORT = 5000; private static final String SLAVE_ID = "slaveId"; private static final Offer MESOS_OFFER = Offer.newBuilder() .setId(OfferID.newBuilder().setValue("offerId")) .setFrameworkId(FrameworkID.newBuilder().setValue("frameworkId")) .setSlaveId(SlaveID.newBuilder().setValue(SLAVE_ID)) .setHostname("hostName") .addResources( Resource.newBuilder() .setName("ports") .setType(Type.RANGES) .setRanges( Ranges.newBuilder().addRange(Range.newBuilder().setBegin(PORT).setEnd(PORT)))) .build(); private static final HostOffer OFFER = new HostOffer(MESOS_OFFER, IHostAttributes.build(new HostAttributes())); private static final String PORT_NAME = "http"; private static final IScheduledTask TASK = IScheduledTask.build( new ScheduledTask() .setAssignedTask( new AssignedTask() .setTaskId("taskId") .setTask( new TaskConfig() .setJob(new JobKey("r", "e", "n")) .setExecutorConfig(new ExecutorConfig().setData("opaque data")) .setRequestedPorts(ImmutableSet.of(PORT_NAME))))); private static final TaskGroupKey GROUP_KEY = TaskGroupKey.from(TASK.getAssignedTask().getTask()); private static final TaskInfo TASK_INFO = TaskInfo.newBuilder() .setName("taskName") .setTaskId(TaskID.newBuilder().setValue(Tasks.id(TASK))) .setSlaveId(MESOS_OFFER.getSlaveId()) .build(); private static final Map<String, TaskGroupKey> NO_RESERVATION = ImmutableMap.of(); private static final UnusedResource UNUSED = new UnusedResource(Resources.from(MESOS_OFFER).slot(), OFFER.getAttributes()); private static final ResourceRequest RESOURCE_REQUEST = new ResourceRequest(TASK.getAssignedTask().getTask(), EMPTY); private MutableStoreProvider storeProvider; private StateManager stateManager; private SchedulingFilter filter; private MesosTaskFactory taskFactory; private OfferManager offerManager; private TaskAssigner assigner; private TierManager tierManager; @Before public void setUp() throws Exception { storeProvider = createMock(MutableStoreProvider.class); filter = createMock(SchedulingFilter.class); taskFactory = createMock(MesosTaskFactory.class); stateManager = createMock(StateManager.class); offerManager = createMock(OfferManager.class); tierManager = createMock(TierManager.class); assigner = new TaskAssignerImpl(stateManager, filter, taskFactory, offerManager, tierManager); } @Test public void testAssignNoVetoes() throws Exception { expect(offerManager.getOffers(GROUP_KEY)).andReturn(ImmutableSet.of(OFFER)); offerManager.launchTask(MESOS_OFFER.getId(), TASK_INFO); expect(tierManager.getTier(TASK.getAssignedTask().getTask())).andReturn(DEFAULT); expect(filter.filter(UNUSED, RESOURCE_REQUEST)).andReturn(ImmutableSet.of()); expect( stateManager.assignTask( storeProvider, Tasks.id(TASK), MESOS_OFFER.getHostname(), MESOS_OFFER.getSlaveId(), ImmutableMap.of(PORT_NAME, PORT))) .andReturn(TASK.getAssignedTask()); expect(taskFactory.createFrom(TASK.getAssignedTask(), MESOS_OFFER.getSlaveId())) .andReturn(TASK_INFO); control.replay(); assertTrue( assigner.maybeAssign( storeProvider, new ResourceRequest(TASK.getAssignedTask().getTask(), EMPTY), TaskGroupKey.from(TASK.getAssignedTask().getTask()), Tasks.id(TASK), ImmutableMap.of(SLAVE_ID, GROUP_KEY))); } @Test public void testAssignVetoesWithStaticBan() throws Exception { expect(offerManager.getOffers(GROUP_KEY)).andReturn(ImmutableSet.of(OFFER)); offerManager.banOffer(MESOS_OFFER.getId(), GROUP_KEY); expect(tierManager.getTier(TASK.getAssignedTask().getTask())).andReturn(DEFAULT); expect(filter.filter(UNUSED, RESOURCE_REQUEST)) .andReturn(ImmutableSet.of(Veto.constraintMismatch("denied"))); control.replay(); assertFalse( assigner.maybeAssign( storeProvider, new ResourceRequest(TASK.getAssignedTask().getTask(), EMPTY), TaskGroupKey.from(TASK.getAssignedTask().getTask()), Tasks.id(TASK), NO_RESERVATION)); } @Test public void testAssignVetoesWithNoStaticBan() throws Exception { expect(offerManager.getOffers(GROUP_KEY)).andReturn(ImmutableSet.of(OFFER)); expect(tierManager.getTier(TASK.getAssignedTask().getTask())).andReturn(DEFAULT); expect(filter.filter(UNUSED, RESOURCE_REQUEST)) .andReturn(ImmutableSet.of(Veto.unsatisfiedLimit("limit"))); control.replay(); assertFalse( assigner.maybeAssign( storeProvider, new ResourceRequest(TASK.getAssignedTask().getTask(), EMPTY), TaskGroupKey.from(TASK.getAssignedTask().getTask()), Tasks.id(TASK), NO_RESERVATION)); } @Test public void testAssignmentClearedOnError() throws Exception { expect(offerManager.getOffers(GROUP_KEY)).andReturn(ImmutableSet.of(OFFER)); offerManager.launchTask(MESOS_OFFER.getId(), TASK_INFO); expectLastCall().andThrow(new OfferManager.LaunchException("expected")); expect(tierManager.getTier(TASK.getAssignedTask().getTask())).andReturn(DEFAULT); expect(filter.filter(UNUSED, RESOURCE_REQUEST)).andReturn(ImmutableSet.of()); expect( stateManager.assignTask( storeProvider, Tasks.id(TASK), MESOS_OFFER.getHostname(), MESOS_OFFER.getSlaveId(), ImmutableMap.of(PORT_NAME, PORT))) .andReturn(TASK.getAssignedTask()); expect( stateManager.changeState( storeProvider, Tasks.id(TASK), Optional.of(PENDING), LOST, LAUNCH_FAILED_MSG)) .andReturn(StateChangeResult.SUCCESS); expect(taskFactory.createFrom(TASK.getAssignedTask(), MESOS_OFFER.getSlaveId())) .andReturn(TASK_INFO); control.replay(); assertFalse( assigner.maybeAssign( storeProvider, new ResourceRequest(TASK.getAssignedTask().getTask(), EMPTY), TaskGroupKey.from(TASK.getAssignedTask().getTask()), Tasks.id(TASK), NO_RESERVATION)); } @Test public void testAssignmentSkippedForReservedSlave() throws Exception { expect(offerManager.getOffers(GROUP_KEY)).andReturn(ImmutableSet.of(OFFER)); control.replay(); assertFalse( assigner.maybeAssign( storeProvider, new ResourceRequest(TASK.getAssignedTask().getTask(), EMPTY), TaskGroupKey.from(TASK.getAssignedTask().getTask()), Tasks.id(TASK), ImmutableMap.of( SLAVE_ID, TaskGroupKey.from( ITaskConfig.build(new TaskConfig().setJob(new JobKey("other", "e", "n"))))))); } @Test public void testTaskWithReservedSlaveLandsElsewhere() throws Exception { // Ensures slave/task reservation relationship is only enforced in slave->task direction // and permissive in task->slave direction. In other words, a task with a slave reservation // should still be tried against other unreserved slaves. HostOffer offer = new HostOffer( Offer.newBuilder() .setId(OfferID.newBuilder().setValue("offerId0")) .setFrameworkId(FrameworkID.newBuilder().setValue("frameworkId")) .setSlaveId(SlaveID.newBuilder().setValue("slaveId0")) .setHostname("hostName0") .addResources( Resource.newBuilder() .setName("ports") .setType(Type.RANGES) .setRanges( Ranges.newBuilder() .addRange(Range.newBuilder().setBegin(PORT).setEnd(PORT)))) .build(), IHostAttributes.build(new HostAttributes())); expect(offerManager.getOffers(GROUP_KEY)).andReturn(ImmutableSet.of(offer, OFFER)); expect(tierManager.getTier(TASK.getAssignedTask().getTask())).andReturn(DEFAULT); expect(filter.filter(UNUSED, RESOURCE_REQUEST)).andReturn(ImmutableSet.of()); expect( stateManager.assignTask( storeProvider, Tasks.id(TASK), offer.getOffer().getHostname(), offer.getOffer().getSlaveId(), ImmutableMap.of(PORT_NAME, PORT))) .andReturn(TASK.getAssignedTask()); expect(taskFactory.createFrom(TASK.getAssignedTask(), offer.getOffer().getSlaveId())) .andReturn(TASK_INFO); offerManager.launchTask(offer.getOffer().getId(), TASK_INFO); control.replay(); assertTrue( assigner.maybeAssign( storeProvider, new ResourceRequest(TASK.getAssignedTask().getTask(), EMPTY), TaskGroupKey.from(TASK.getAssignedTask().getTask()), Tasks.id(TASK), ImmutableMap.of(SLAVE_ID, GROUP_KEY))); } @Test public void testAssignerDoesNotReturnOnFirstMismatch() throws Exception { // Ensures scheduling loop does not terminate prematurely when the first mismatch is identified. HostOffer mismatched = new HostOffer( Offer.newBuilder() .setId(OfferID.newBuilder().setValue("offerId0")) .setFrameworkId(FrameworkID.newBuilder().setValue("frameworkId")) .setSlaveId(SlaveID.newBuilder().setValue("slaveId0")) .setHostname("hostName0") .addResources( Resource.newBuilder() .setName("ports") .setType(Type.RANGES) .setRanges( Ranges.newBuilder() .addRange(Range.newBuilder().setBegin(PORT).setEnd(PORT)))) .build(), IHostAttributes.build(new HostAttributes())); expect(offerManager.getOffers(GROUP_KEY)).andReturn(ImmutableSet.of(mismatched, OFFER)); expect(tierManager.getTier(TASK.getAssignedTask().getTask())).andReturn(DEFAULT).times(2); expect( filter.filter( new UnusedResource( Resources.from(mismatched.getOffer()).slot(), mismatched.getAttributes()), new ResourceRequest(TASK.getAssignedTask().getTask(), EMPTY))) .andReturn(ImmutableSet.of(Veto.constraintMismatch("constraint mismatch"))); offerManager.banOffer(mismatched.getOffer().getId(), GROUP_KEY); expect( filter.filter( new UnusedResource(Resources.from(OFFER.getOffer()).slot(), OFFER.getAttributes()), new ResourceRequest(TASK.getAssignedTask().getTask(), EMPTY))) .andReturn(ImmutableSet.of()); expect( stateManager.assignTask( storeProvider, Tasks.id(TASK), OFFER.getOffer().getHostname(), OFFER.getOffer().getSlaveId(), ImmutableMap.of(PORT_NAME, PORT))) .andReturn(TASK.getAssignedTask()); expect(taskFactory.createFrom(TASK.getAssignedTask(), OFFER.getOffer().getSlaveId())) .andReturn(TASK_INFO); offerManager.launchTask(OFFER.getOffer().getId(), TASK_INFO); control.replay(); assertTrue( assigner.maybeAssign( storeProvider, new ResourceRequest(TASK.getAssignedTask().getTask(), EMPTY), TaskGroupKey.from(TASK.getAssignedTask().getTask()), Tasks.id(TASK), ImmutableMap.of(SLAVE_ID, GROUP_KEY))); } }
public class TaskAssignerImplTest extends EasyMockTest { private static final int PORT = 5000; private static final Offer MESOS_OFFER = Offer.newBuilder() .setId(OfferID.newBuilder().setValue("offerId")) .setFrameworkId(FrameworkID.newBuilder().setValue("frameworkId")) .setSlaveId(SlaveID.newBuilder().setValue("slaveId")) .setHostname("hostName") .addResources( Resource.newBuilder() .setName("ports") .setType(Type.RANGES) .setRanges( Ranges.newBuilder().addRange(Range.newBuilder().setBegin(PORT).setEnd(PORT)))) .build(); private static final HostOffer OFFER = new HostOffer(MESOS_OFFER, IHostAttributes.build(new HostAttributes())); private static final String PORT_NAME = "http"; private static final IScheduledTask TASK = IScheduledTask.build( new ScheduledTask() .setAssignedTask( new AssignedTask() .setTaskId("taskId") .setTask( new TaskConfig() .setExecutorConfig(new ExecutorConfig().setData("opaque data")) .setRequestedPorts(ImmutableSet.of(PORT_NAME))))); private static final TaskInfo TASK_INFO = TaskInfo.newBuilder() .setName("taskName") .setTaskId(TaskID.newBuilder().setValue(Tasks.id(TASK))) .setSlaveId(MESOS_OFFER.getSlaveId()) .build(); private MutableStoreProvider storeProvider; private StateManager stateManager; private SchedulingFilter filter; private MesosTaskFactory taskFactory; private TaskAssigner assigner; @Before public void setUp() throws Exception { storeProvider = createMock(MutableStoreProvider.class); stateManager = createMock(StateManager.class); filter = createMock(SchedulingFilter.class); taskFactory = createMock(MesosTaskFactory.class); assigner = new TaskAssignerImpl(stateManager, filter, taskFactory); } @Test public void testAssignNoVetoes() { expect( filter.filter( new UnusedResource(ResourceSlot.from(MESOS_OFFER), OFFER.getAttributes()), new ResourceRequest(TASK.getAssignedTask().getTask(), EMPTY))) .andReturn(ImmutableSet.of()); expect( stateManager.assignTask( storeProvider, Tasks.id(TASK), MESOS_OFFER.getHostname(), MESOS_OFFER.getSlaveId(), ImmutableMap.of(PORT_NAME, PORT))) .andReturn(TASK.getAssignedTask()); expect(taskFactory.createFrom(TASK.getAssignedTask(), MESOS_OFFER.getSlaveId())) .andReturn(TASK_INFO); control.replay(); assertEquals( Assignment.success(TASK_INFO), assigner.maybeAssign( storeProvider, OFFER, new ResourceRequest(TASK.getAssignedTask().getTask(), EMPTY), Tasks.id(TASK))); } @Test public void testAssignVetoes() { expect( filter.filter( new UnusedResource(ResourceSlot.from(MESOS_OFFER), OFFER.getAttributes()), new ResourceRequest(TASK.getAssignedTask().getTask(), EMPTY))) .andReturn(ImmutableSet.of(Veto.constraintMismatch("denied"))); control.replay(); assertEquals( Assignment.failure(ImmutableSet.of(Veto.constraintMismatch("denied"))), assigner.maybeAssign( storeProvider, OFFER, new ResourceRequest(TASK.getAssignedTask().getTask(), EMPTY), Tasks.id(TASK))); } }