package com.hubspot.singularity.scheduler; import java.util.Arrays; import java.util.Collections; import java.util.List; import org.apache.mesos.Protos.TaskState; import org.junit.Assert; import org.junit.Test; import com.google.common.base.Optional; import com.google.inject.Inject; import com.hubspot.mesos.json.MesosTaskMonitorObject; import com.hubspot.mesos.json.MesosTaskStatisticsObject; import com.hubspot.singularity.MachineState; import com.hubspot.singularity.SingularityTask; import com.hubspot.singularity.SingularityTaskCurrentUsageWithId; import com.hubspot.singularity.SingularityTaskId; import com.hubspot.singularity.SingularityTaskUsage; import com.hubspot.singularity.data.UsageManager; public class SingularityUsageTest extends SingularitySchedulerTestBase { @Inject protected SingularityUsagePoller usagePoller; @Inject protected SingularityUsageCleanerPoller cleaner; @Inject protected UsageManager usageManager; @Inject protected TestingMesosClient mesosClient; public SingularityUsageTest() { super(false); } @Test public void testUsagePollerSimple() { // works with no slaves usagePoller.runActionOnPoll(); cleaner.runActionOnPoll(); initRequest(); initFirstDeploy(); saveAndSchedule(request.toBuilder().setInstances(Optional.of(1))); resourceOffers(1); SingularityTask firstTask = taskManager.getActiveTasks().get(0); String hostname = firstTask.getOffer().getHostname(); MesosTaskMonitorObject usage = new MesosTaskMonitorObject(null, null, null, firstTask.getTaskId().getId(), getStatistics(2, 5, 100)); mesosClient.setSlaveResourceUsage(hostname, Collections.singletonList(usage)); usagePoller.runActionOnPoll(); String slaveId = firstTask.getOffer().getSlaveId().getValue().toString(); List<String> slaves = usageManager.getSlavesWithUsage(); Assert.assertEquals(1, slaves.size()); Assert.assertEquals(slaves.get(0), slaveId); Assert.assertEquals(0, usageManager.getSlaveUsage(slaveId).get(0).getCpusUsed(), 0); Assert.assertEquals(100, usageManager.getSlaveUsage(slaveId).get(0).getMemoryBytesUsed()); SingularityTaskUsage first = usageManager.getTaskUsage(firstTask.getTaskId().getId()).get(0); Assert.assertEquals(2, first.getCpuSeconds(), 0); Assert.assertEquals(100, first.getMemoryRssBytes(), 0); Assert.assertEquals(5, first.getTimestamp(), 0); } @Test public void testUsageCleaner() { initRequest(); initFirstDeploy(); saveAndSchedule(request.toBuilder().setInstances(Optional.of(2))); resourceOffers(1); List<SingularityTaskId> taskIds = taskManager.getActiveTaskIds(); String t1 = taskIds.get(0).getId(); String t2 = taskIds.get(1).getId(); String slaveId = slaveManager.getObjectIds().get(0); String host = slaveManager.getObjects().get(0).getHost(); MesosTaskMonitorObject t1u1 = new MesosTaskMonitorObject(null, null, null, t1, getStatistics(2, 5, 100)); MesosTaskMonitorObject t2u1 = new MesosTaskMonitorObject(null, null, null, t2, getStatistics(10, 5, 1000)); mesosClient.setSlaveResourceUsage(host, Arrays.asList(t1u1, t2u1)); usagePoller.runActionOnPoll(); cleaner.runActionOnPoll(); Assert.assertEquals(2, usageManager.getTasksWithUsage().size()); Assert.assertEquals(1, usageManager.getSlavesWithUsage().size()); Assert.assertEquals(1100, usageManager.getAllCurrentSlaveUsage().get(0).getMemoryBytesUsed()); // kill task one statusUpdate(taskManager.getActiveTasks().get(0), TaskState.TASK_KILLED); killKilledTasks(); cleaner.runActionOnPoll(); Assert.assertEquals(1, usageManager.getTasksWithUsage().size()); Assert.assertEquals(1, usageManager.getSlavesWithUsage().size()); slaveManager.changeState(slaveId, MachineState.DEAD, Optional.<String> absent(), Optional.<String> absent()); cleaner.runActionOnPoll(); Assert.assertEquals(1, usageManager.getTasksWithUsage().size()); Assert.assertEquals(0, usageManager.getSlavesWithUsage().size()); } @Test public void testUsagePollerComplex() throws InterruptedException { initRequest(); initFirstDeploy(); saveAndSchedule(request.toBuilder().setInstances(Optional.of(2))); resourceOffers(1); configuration.setNumUsageToKeep(2); List<SingularityTaskId> taskIds = taskManager.getActiveTaskIds(); String t1 = taskIds.get(0).getId(); String t2 = taskIds.get(1).getId(); String slaveId = slaveManager.getObjectIds().get(0); String host = slaveManager.getObjects().get(0).getHost(); MesosTaskMonitorObject t1u1 = new MesosTaskMonitorObject(null, null, null, t1, getStatistics(2, 5, 100)); MesosTaskMonitorObject t2u1 = new MesosTaskMonitorObject(null, null, null, t2, getStatistics(10, 5, 1000)); mesosClient.setSlaveResourceUsage(host, Arrays.asList(t1u1, t2u1)); usagePoller.runActionOnPoll(); cleaner.runActionOnPoll(); Thread.sleep(2); // 5 seconds have elapsed, t1 has used 1 CPU the whole time = 5 + 2 // t2 has used 2.5 CPUs the whole time = MesosTaskMonitorObject t1u2 = new MesosTaskMonitorObject(null, null, null, t1, getStatistics(7, 10, 125)); MesosTaskMonitorObject t2u2 = new MesosTaskMonitorObject(null, null, null, t2, getStatistics(22.5, 10, 750)); mesosClient.setSlaveResourceUsage(host, Arrays.asList(t1u2, t2u2)); usagePoller.runActionOnPoll(); cleaner.runActionOnPoll(); // check usage now Assert.assertEquals(3.5, usageManager.getSlaveUsage(slaveId).get(1).getCpusUsed(), 0); Assert.assertEquals(875, usageManager.getSlaveUsage(slaveId).get(1).getMemoryBytesUsed(), 0); Assert.assertEquals(2, usageManager.getSlaveUsage(slaveId).get(1).getNumTasks(), 0); // check task usage Assert.assertEquals(22.5, usageManager.getTaskUsage(t2).get(1).getCpuSeconds(), 0); Assert.assertEquals(10, usageManager.getTaskUsage(t2).get(0).getCpuSeconds(), 0); Thread.sleep(2); MesosTaskMonitorObject t1u3 = new MesosTaskMonitorObject(null, null, null, t1, getStatistics(8, 11, 125)); MesosTaskMonitorObject t2u3 = new MesosTaskMonitorObject(null, null, null, t2, getStatistics(23.5, 11, 1000)); mesosClient.setSlaveResourceUsage(host, Arrays.asList(t1u3, t2u3)); usagePoller.runActionOnPoll(); cleaner.runActionOnPoll(); //check that there is only 2 usages Assert.assertEquals(2, usageManager.getSlaveUsage(slaveId).size()); Assert.assertEquals(2, usageManager.getTaskUsage(t1).size()); Assert.assertEquals(2, usageManager.getTaskUsage(t2).size()); Assert.assertEquals(22.5, usageManager.getTaskUsage(t2).get(0).getCpuSeconds(), 0); Assert.assertEquals(23.5, usageManager.getTaskUsage(t2).get(1).getCpuSeconds(), 0); Assert.assertEquals(875, usageManager.getSlaveUsage(slaveId).get(0).getMemoryBytesUsed(), 0); Assert.assertEquals(1125, usageManager.getSlaveUsage(slaveId).get(1).getMemoryBytesUsed(), 0); Assert.assertEquals(slaveId, usageManager.getAllCurrentSlaveUsage().get(0).getSlaveId()); Assert.assertEquals(1125, usageManager.getAllCurrentSlaveUsage().get(0).getMemoryBytesUsed()); List<SingularityTaskCurrentUsageWithId> taskCurrentUsages = usageManager.getTaskCurrentUsages(taskManager.getActiveTaskIds()); Assert.assertEquals(2, taskCurrentUsages.size()); List<SingularityTaskId> activeTaskIds = taskManager.getActiveTaskIds(); for (SingularityTaskCurrentUsageWithId taskCurrentUsage : taskCurrentUsages) { activeTaskIds.remove(taskCurrentUsage.getTaskId()); } Assert.assertTrue(activeTaskIds.isEmpty()); } private MesosTaskStatisticsObject getStatistics(double cpuSecs, double timestamp, long memBytes) { return new MesosTaskStatisticsObject(1, 0L, 0L, 0, 0, cpuSecs, 0L, 0L, 0L, 0L, memBytes, timestamp); } }