/* * Copyright 2015 Netflix, Inc. * * Licensed 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. */ package com.netflix.fenzo; import com.netflix.fenzo.plugins.BinPackingFitnessCalculators; import org.junit.Assert; import org.apache.mesos.Protos; import org.junit.After; import org.junit.Before; import org.junit.Test; import com.netflix.fenzo.functions.Action1; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; public class ActiveVmGroupsTests { private static final String activeVmGrpAttrName = "ASG"; private static final String activeVmGrp = "test1"; private TaskScheduler taskScheduler; private final Map<String, Protos.Attribute> attributes1 = new HashMap<>(); private final Map<String, Protos.Attribute> attributes2 = new HashMap<>(); @Before public void setUp() throws Exception { taskScheduler = new TaskScheduler.Builder() .withLeaseOfferExpirySecs(1000000) .withLeaseRejectAction(new Action1<VirtualMachineLease>() { @Override public void call(VirtualMachineLease virtualMachineLease) { System.out.println("Rejecting offer on host " + virtualMachineLease.hostname()); } }) .build(); taskScheduler.setActiveVmGroupAttributeName(activeVmGrpAttrName); taskScheduler.setActiveVmGroups(Arrays.asList(activeVmGrp)); Protos.Attribute attribute1 = Protos.Attribute.newBuilder().setName(activeVmGrpAttrName) .setType(Protos.Value.Type.TEXT) .setText(Protos.Value.Text.newBuilder().setValue("test1")).build(); attributes1.put(activeVmGrpAttrName, attribute1); Protos.Attribute attribute2 = Protos.Attribute.newBuilder().setName(activeVmGrpAttrName) .setType(Protos.Value.Type.TEXT) .setText(Protos.Value.Text.newBuilder().setValue("test2")).build(); attributes2.put(activeVmGrpAttrName, attribute2); } @After public void tearDown() throws Exception { } @Test public void testInactiveVmGroup() { List<VirtualMachineLease.Range> ports = new ArrayList<>(); ports.add(new VirtualMachineLease.Range(1, 10)); List<VirtualMachineLease> leases = Collections.singletonList(LeaseProvider.getLeaseOffer("host1", 4, 4000, ports, attributes2)); List<TaskRequest> tasks = Collections.singletonList(TaskRequestProvider.getTaskRequest(1, 1000, 1)); Map<String, VMAssignmentResult> resultMap = taskScheduler.scheduleOnce(tasks, leases).getResultMap(); Assert.assertEquals(0, resultMap.size()); leases = Collections.singletonList(LeaseProvider.getLeaseOffer("host2", 4, 4000, ports, attributes1)); resultMap = taskScheduler.scheduleOnce(tasks, leases).getResultMap(); Assert.assertEquals(1, resultMap.size()); Assert.assertEquals(tasks.get(0).getId(), resultMap.values().iterator().next().getTasksAssigned().iterator().next().getTaskId()); } @Test public void testOffersRejectOnInactiveVMs() { final Set<String> hostsSet = new HashSet<>(); for(int i=0; i<10; i++) hostsSet.add("host"+i); TaskScheduler ts = new TaskScheduler.Builder() .withLeaseOfferExpirySecs(2) .withLeaseRejectAction(new Action1<VirtualMachineLease>() { @Override public void call(VirtualMachineLease lease) { hostsSet.remove(lease.hostname()); } }) .build(); ts.setActiveVmGroupAttributeName(activeVmGrpAttrName); ts.setActiveVmGroups(Arrays.asList(activeVmGrp)); List<VirtualMachineLease> leases = new ArrayList<>(); List<VirtualMachineLease.Range> ports = new ArrayList<>(); ports.add(new VirtualMachineLease.Range(1, 10)); for(String h: hostsSet) { leases.add(LeaseProvider.getLeaseOffer(h, 4, 4000, ports, attributes2)); } leases.add(LeaseProvider.getLeaseOffer("hostA", 4, 4000, ports, attributes1)); leases.add(LeaseProvider.getLeaseOffer("hostB", 4, 4000, ports, attributes1)); ts.scheduleOnce(Collections.EMPTY_LIST, leases); for(int i=0; i< 3; i++) { ts.scheduleOnce(Collections.EMPTY_LIST, Collections.EMPTY_LIST); System.out.println("..."); try{Thread.sleep(1000);}catch(InterruptedException ie){} } System.out.println("Not rejected leases for " + hostsSet.size() + " hosts"); Assert.assertEquals(0, hostsSet.size()); } @Test public void testRandomizedOfferRejection() { final Set<String> hostsSet = new HashSet<>(); final List<String> hostsToAdd = new ArrayList<>(); final List<VirtualMachineLease> leases = LeaseProvider.getLeases(10, 4, 4000, 1, 10); TaskScheduler ts = new TaskScheduler.Builder() .withLeaseOfferExpirySecs(2) .withLeaseRejectAction(new Action1<VirtualMachineLease>() { @Override public void call(VirtualMachineLease virtualMachineLease) { hostsSet.add(virtualMachineLease.hostname()); hostsToAdd.add(virtualMachineLease.hostname()); } }) .build(); for(int i=0; i<9; i++) { if(!hostsToAdd.isEmpty()) { for(String h: hostsToAdd) leases.add(LeaseProvider.getLeaseOffer(h, 4, 4000, 1, 10)); hostsToAdd.clear(); } ts.scheduleOnce(Collections.EMPTY_LIST, leases); leases.clear(); try{Thread.sleep(1000);}catch(InterruptedException ie){} } Assert.assertTrue(hostsSet.size()>2); } // Test that having two different asg types enabled and a task asking for larger #cpus, that only fits on one of the // types, works when both asg types are enabled. @Test public void testActiveASGsOfTwoTypes() throws Exception { TaskScheduler scheduler = new TaskScheduler.Builder() .withFitnessCalculator(BinPackingFitnessCalculators.cpuMemBinPacker) .withLeaseOfferExpirySecs(100000000) .withLeaseRejectAction(new Action1<VirtualMachineLease>() { @Override public void call(VirtualMachineLease virtualMachineLease) { Assert.fail("Unexpected to reject lease"); //System.out.println("Rejecting lease on " + virtualMachineLease.hostname()); } }) .build(); scheduler.setActiveVmGroupAttributeName("ASG"); scheduler.setActiveVmGroups(Arrays.asList("8cores", "16cores")); final List<VirtualMachineLease> leases = new ArrayList<>(); int nHosts8core=3; int nHosts16core=1; List<VirtualMachineLease.Range> ports = new ArrayList<>(); ports.add(new VirtualMachineLease.Range(1, 100)); Map<String, Protos.Attribute> attributes = new HashMap<>(); Protos.Attribute attribute = Protos.Attribute.newBuilder().setName("ASG") .setType(Protos.Value.Type.TEXT) .setText(Protos.Value.Text.newBuilder().setValue("8cores")).build(); attributes.put("ASG", attribute); for(int l=0; l<nHosts8core; l++) leases.add(LeaseProvider.getLeaseOffer("host"+l, 8, 32000, 1024.0, ports, attributes)); attributes = new HashMap<>(); Protos.Attribute attribute2 = Protos.Attribute.newBuilder().setName("ASG") .setType(Protos.Value.Type.TEXT) .setText(Protos.Value.Text.newBuilder().setValue("16cores")).build(); attributes.put("ASG", attribute2); for(int l=0; l<nHosts16core; l++) leases.add(LeaseProvider.getLeaseOffer("bighost" + l, 16, 64000, 1024.0, ports, attributes)); List<TaskRequest> tasks = Arrays.asList(TaskRequestProvider.getTaskRequest(1, 100, 1)); SchedulingResult schedulingResult = scheduler.scheduleOnce(tasks, leases); Assert.assertEquals(1, schedulingResult.getResultMap().size()); System.out.println("result map #elements: " + schedulingResult.getResultMap().size()); Assert.assertEquals(0, schedulingResult.getFailures().size()); schedulingResult = scheduler.scheduleOnce(Arrays.asList(TaskRequestProvider.getTaskRequest(16, 1000, 1)), Collections.EMPTY_LIST); Assert.assertEquals(1, schedulingResult.getResultMap().size()); System.out.println("result map #elements: " + schedulingResult.getResultMap().size()); Assert.assertEquals(0, schedulingResult.getFailures().size()); } }