/*
* 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.functions.Action1;
import org.apache.mesos.Protos;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import static org.junit.Assert.*;
public class VMCollectionTest {
private final Map<String, Protos.Attribute> attributes1 = new HashMap<>();
private final Map<String, Protos.Attribute> activeVmAttribute1 = new HashMap<>();
private final Map<String, Protos.Attribute> activeVmAttribute2 = new HashMap<>();
private final List<VirtualMachineLease.Range> ports = new ArrayList<>();
private final String attributeVal1 = "4cores";
private final String vmAttrVal1 = "val1";
private final String vmAttrVal2 = "val2";
private final String activeAttr = "Asg";
@Before
public void setUp() throws Exception {
Protos.Attribute attribute = Protos.Attribute.newBuilder().setName(activeAttr)
.setType(Protos.Value.Type.TEXT)
.setText(Protos.Value.Text.newBuilder().setValue(attributeVal1)).build();
attributes1.put(AutoScalerTest.hostAttrName, attribute);
Protos.Attribute vmAttr1 = Protos.Attribute.newBuilder().setName(activeAttr)
.setType(Protos.Value.Type.TEXT)
.setText(Protos.Value.Text.newBuilder().setValue(vmAttrVal1)).build();
activeVmAttribute1.put(activeAttr, vmAttr1);
activeVmAttribute1.put(AutoScalerTest.hostAttrName, attribute);
Protos.Attribute vmAttr2 = Protos.Attribute.newBuilder().setName(activeAttr)
.setType(Protos.Value.Type.TEXT)
.setText(Protos.Value.Text.newBuilder().setValue(vmAttrVal2)).build();
activeVmAttribute2.put(activeAttr, vmAttr2);
activeVmAttribute2.put(AutoScalerTest.hostAttrName, attribute);
ports.add(new VirtualMachineLease.Range(1, 100));
}
@Test
public void clonePseudoVMsForGroups() throws Exception {
AutoScaleRule rule = getAutoScaleRule(attributeVal1, 4);
Action1<VirtualMachineLease> leaseRejectAction = l -> {};
final ConcurrentMap<String, String> vmIdTohostNames = new ConcurrentHashMap<>();
final ConcurrentMap<String, String> leasesToHostnames = new ConcurrentHashMap<>();
final Map<String, AssignableVirtualMachine> avms = new HashMap<>();
final TaskTracker taskTracker = new TaskTracker();
VMCollection vms = createVmCollection(vmIdTohostNames, leasesToHostnames, taskTracker, avms);
for (int i=0; i < rule.getMaxSize()-1; i++) {
vms.addLease(LeaseProvider.getLeaseOffer("host"+i, 4, 4000,
0, 0, ports, attributes1, Collections.singletonMap("GPU", 1.0)));
}
for (AssignableVirtualMachine avm: avms.values())
avm.updateCurrTotalLease();
final Map<String, List<String>> map = vms.clonePseudoVMsForGroups(
Collections.singletonMap(rule.getRuleName(), 6), s -> rule,
lease -> true
);
Assert.assertNotNull(map);
Assert.assertEquals(1, map.size());
Assert.assertEquals(rule.getRuleName(), map.keySet().iterator().next());
Assert.assertEquals(1, map.values().iterator().next().size());
}
@Test
public void testWithInactiveAgents() throws Exception {
AutoScaleRule rule = getAutoScaleRule(attributeVal1, 4);
final ConcurrentMap<String, String> vmIdTohostNames = new ConcurrentHashMap<>();
final ConcurrentMap<String, String> leasesToHostnames = new ConcurrentHashMap<>();
final Map<String, AssignableVirtualMachine> avms = new HashMap<>();
TaskTracker taskTracker = new TaskTracker();
VMCollection vms = createVmCollection(vmIdTohostNames, leasesToHostnames, taskTracker, avms);
// create leases for ruleMax-2 VMs for each of vmAttrVal1 and vmAttrVal2
for (int i=0; i<rule.getMaxSize()-2; i++) {
vms.addLease(LeaseProvider.getLeaseOffer("host-a1-"+i, 4, 4000, 0, 0,
ports, activeVmAttribute1, Collections.singletonMap("GPU", 1.0)));
vms.addLease(LeaseProvider.getLeaseOffer("host-a2-"+i, 4, 4000, 0, 0,
ports, activeVmAttribute2, Collections.singletonMap("GPU", 1.0)));
}
for (AssignableVirtualMachine avm: avms.values())
avm.updateCurrTotalLease();
final Map<String, List<String>> map = vms.clonePseudoVMsForGroups(
Collections.singletonMap(rule.getRuleName(), 7), s -> rule,
lease -> {
System.out.println("Comparing " + vmAttrVal2 + " with " + lease.getAttributeMap().get(activeAttr).getText().getValue());
return vmAttrVal2.equals(lease.getAttributeMap().get(activeAttr).getText().getValue());
}
);
Assert.assertNotNull(map);
Assert.assertEquals(1, map.size());
Assert.assertEquals(2, map.values().iterator().next().size());
for (String h: map.values().iterator().next()) {
final AssignableVirtualMachine avm = avms.get(h);
Assert.assertNotNull(avm);
avm.updateCurrTotalLease();
final String attrValue = avm.getAttrValue(activeAttr);
Assert.assertTrue("Invalid to get host " + h + " with attrVal " + attrValue,
vmAttrVal2.equals(attrValue));
}
}
private VMCollection createVmCollection(ConcurrentMap<String, String> vmIdTohostNames,
ConcurrentMap<String, String> leasesToHostnames, TaskTracker taskTracker,
Map<String, AssignableVirtualMachine> avms) {
Action1<VirtualMachineLease> leaseRejectAction = l -> {};
return new VMCollection(s -> {
AssignableVirtualMachine avm = new AssignableVirtualMachine(
vmIdTohostNames,
leasesToHostnames,
s,
leaseRejectAction,
2,
taskTracker,
false
);
avms.put(s, avm);
return avm;
}, AutoScalerTest.hostAttrName);
}
private AutoScaleRule getAutoScaleRule(final String name, final int maxSize) {
return new AutoScaleRule() {
@Override
public String getRuleName() {
return name;
}
@Override
public int getMinIdleHostsToKeep() {
return 0;
}
@Override
public int getMaxIdleHostsToKeep() {
return 0;
}
@Override
public int getMaxSize() {
return maxSize;
}
@Override
public long getCoolDownSecs() {
return 1;
}
@Override
public boolean idleMachineTooSmall(VirtualMachineLease lease) {
return false;
}
};
}
}