Merge pull request #656 from koushik-das/CLOUDSTACK-8704

CLOUDSTACK-8704: Schedule restart of router VMs ahead of user VMs as part of HA

VRs are scheduled for HA ahead of user VMs.

Refer to the bug for more details.

* pr/656:
  CLOUDSTACK-8704: Schedule restart of router VMs ahead of user VMs as part of HA VRs are scheduled for HA ahead of user VMs

Signed-off-by: Remi Bergsma <github@remi.nl>
This commit is contained in:
Remi Bergsma 2015-08-10 12:13:15 +02:00
commit cd02a59841
2 changed files with 74 additions and 36 deletions

View File

@ -31,7 +31,6 @@ import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import org.apache.log4j.NDC;
import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.managed.context.ManagedContext;
@ -231,7 +230,7 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements HighAvai
}
if (host.getHypervisorType() == HypervisorType.VMware || host.getHypervisorType() == HypervisorType.Hyperv) {
s_logger.info("Don't restart for VMs on host " + host.getId() + " as the host is VMware host or on Hyperv Host");
s_logger.info("Don't restart VMs on host " + host.getId() + " as it is a " + host.getHypervisorType().toString() + " host");
return;
}
@ -242,16 +241,18 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements HighAvai
// send an email alert that the host is down
StringBuilder sb = null;
List<VMInstanceVO> reorderedVMList = new ArrayList<VMInstanceVO>();
if ((vms != null) && !vms.isEmpty()) {
sb = new StringBuilder();
sb.append(" Starting HA on the following VMs: ");
sb.append(" Starting HA on the following VMs:");
// collect list of vm names for the alert email
VMInstanceVO vm = vms.get(0);
if (vm.isHaEnabled()) {
sb.append(" " + vm);
}
for (int i = 1; i < vms.size(); i++) {
vm = vms.get(i);
for (int i = 0; i < vms.size(); i++) {
VMInstanceVO vm = vms.get(i);
if (vm.getType() == VirtualMachine.Type.User) {
reorderedVMList.add(vm);
} else {
reorderedVMList.add(0, vm);
}
if (vm.isHaEnabled()) {
sb.append(" " + vm.getHostName());
}
@ -261,25 +262,21 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements HighAvai
// send an email alert that the host is down, include VMs
HostPodVO podVO = _podDao.findById(host.getPodId());
String hostDesc = "name: " + host.getName() + " (id:" + host.getId() + "), availability zone: " + dcVO.getName() + ", pod: " + podVO.getName();
_alertMgr.sendAlert(AlertManager.AlertType.ALERT_TYPE_HOST, host.getDataCenterId(), host.getPodId(), "Host is down, " + hostDesc,
"Host [" + hostDesc + "] is down." + ((sb != null) ? sb.toString() : ""));
_alertMgr.sendAlert(AlertManager.AlertType.ALERT_TYPE_HOST, host.getDataCenterId(), host.getPodId(), "Host is down, " + hostDesc, "Host [" + hostDesc +
"] is down." +
((sb != null) ? sb.toString() : ""));
if (vms != null) {
for (VMInstanceVO vm : vms) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Notifying HA Mgr of to restart vm " + vm.getId() + "-" + vm.getInstanceName());
}
vm = _instanceDao.findByUuid(vm.getUuid());
Long hostId = vm.getHostId();
if (hostId != null && !hostId.equals(host.getId())) {
s_logger.debug("VM " + vm.getInstanceName() + " is not on down host " + host.getId() + " it is on other host "
+ hostId + " VM HA is done");
continue;
}
scheduleRestart(vm, investigate);
for (VMInstanceVO vm : reorderedVMList) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Notifying HA Mgr of to restart vm " + vm.getId() + "-" + vm.getInstanceName());
}
vm = _instanceDao.findByUuid(vm.getUuid());
Long hostId = vm.getHostId();
if (hostId != null && !hostId.equals(host.getId())) {
s_logger.debug("VM " + vm.getInstanceName() + " is not on down host " + host.getId() + " it is on other host "
+ hostId + " VM HA is done");
continue;
}
scheduleRestart(vm, investigate);
}
}

View File

@ -19,6 +19,7 @@ package com.cloud.ha;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
@ -57,6 +58,7 @@ import com.cloud.storage.dao.GuestOSCategoryDao;
import com.cloud.storage.dao.GuestOSDao;
import com.cloud.user.AccountManager;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineManager;
import com.cloud.vm.dao.VMInstanceDao;
@ -74,13 +76,10 @@ public class HighAvailabilityManagerImplTest {
HostPodDao _podDao;
@Mock
ClusterDetailsDao _clusterDetailsDao;
@Mock
ServiceOfferingDao _serviceOfferingDao;
@Mock
ManagedContext _managedContext;
@Mock
AgentManager _agentMgr;
@Mock
@ -103,7 +102,6 @@ public class HighAvailabilityManagerImplTest {
ConfigurationDao _configDao;
@Mock
VolumeOrchestrationService volumeMgr;
@Mock
HostVO hostVO;
@ -113,12 +111,18 @@ public class HighAvailabilityManagerImplTest {
public void setup() throws IllegalArgumentException,
IllegalAccessException, NoSuchFieldException, SecurityException {
highAvailabilityManager = new HighAvailabilityManagerImpl();
for (Field injectField : HighAvailabilityManagerImpl.class
.getDeclaredFields()) {
for (Field injectField : HighAvailabilityManagerImpl.class.getDeclaredFields()) {
if (injectField.isAnnotationPresent(Inject.class)) {
injectField.setAccessible(true);
injectField.set(highAvailabilityManager, this.getClass()
.getDeclaredField(injectField.getName()).get(this));
injectField.set(highAvailabilityManager, this.getClass().getDeclaredField(injectField.getName()).get(this));
} else if (injectField.getName().equals("_workers")) {
injectField.setAccessible(true);
for (Class<?> clz : HighAvailabilityManagerImpl.class.getDeclaredClasses()) {
if (clz.getName().equals("com.cloud.ha.HighAvailabilityManagerImpl$WorkerThread")) {
Object obj = Array.newInstance(clz, 0);
injectField.set(highAvailabilityManager, obj);
}
}
}
}
}
@ -127,10 +131,47 @@ public class HighAvailabilityManagerImplTest {
public void scheduleRestartForVmsOnHost() {
Mockito.when(hostVO.getType()).thenReturn(Host.Type.Routing);
Mockito.when(hostVO.getHypervisorType()).thenReturn(HypervisorType.KVM);
Mockito.when(_instanceDao.listByHostId(42l)).thenReturn(
Arrays.asList(Mockito.mock(VMInstanceVO.class)));
Mockito.when(_instanceDao.listByHostId(42l)).thenReturn(Arrays.asList(Mockito.mock(VMInstanceVO.class)));
Mockito.when(_podDao.findById(Mockito.anyLong())).thenReturn(Mockito.mock(HostPodVO.class));
Mockito.when(_dcDao.findById(Mockito.anyLong())).thenReturn(Mockito.mock(DataCenterVO.class));
highAvailabilityManager.scheduleRestartForVmsOnHost(hostVO, true);
}
@Test
public void scheduleRestartForVmsOnHostNotSupported() {
Mockito.when(hostVO.getType()).thenReturn(Host.Type.Routing);
Mockito.when(hostVO.getHypervisorType()).thenReturn(HypervisorType.VMware);
highAvailabilityManager.scheduleRestartForVmsOnHost(hostVO, true);
}
@Test
public void scheduleRestartForVmsOnHostNonEmptyVMList() {
Mockito.when(hostVO.getId()).thenReturn(1l);
Mockito.when(hostVO.getType()).thenReturn(Host.Type.Routing);
Mockito.when(hostVO.getHypervisorType()).thenReturn(HypervisorType.XenServer);
List<VMInstanceVO> vms = new ArrayList<VMInstanceVO>();
VMInstanceVO vm1 = Mockito.mock(VMInstanceVO.class);
Mockito.when(vm1.getHostId()).thenReturn(1l);
Mockito.when(vm1.getInstanceName()).thenReturn("i-2-3-VM");
Mockito.when(vm1.getType()).thenReturn(VirtualMachine.Type.User);
Mockito.when(vm1.isHaEnabled()).thenReturn(true);
vms.add(vm1);
VMInstanceVO vm2 = Mockito.mock(VMInstanceVO.class);
Mockito.when(vm2.getHostId()).thenReturn(1l);
Mockito.when(vm2.getInstanceName()).thenReturn("r-2-VM");
Mockito.when(vm2.getType()).thenReturn(VirtualMachine.Type.DomainRouter);
Mockito.when(vm2.isHaEnabled()).thenReturn(true);
vms.add(vm2);
Mockito.when(_instanceDao.listByHostId(Mockito.anyLong())).thenReturn(vms);
Mockito.when(_instanceDao.findByUuid(vm1.getUuid())).thenReturn(vm1);
Mockito.when(_instanceDao.findByUuid(vm2.getUuid())).thenReturn(vm2);
Mockito.when(_podDao.findById(Mockito.anyLong())).thenReturn(Mockito.mock(HostPodVO.class));
Mockito.when(_dcDao.findById(Mockito.anyLong())).thenReturn(Mockito.mock(DataCenterVO.class));
Mockito.when(_haDao.findPreviousHA(Mockito.anyLong())).thenReturn(Arrays.asList(Mockito.mock(HaWorkVO.class)));
Mockito.when(_haDao.persist((HaWorkVO)Mockito.anyObject())).thenReturn(Mockito.mock(HaWorkVO.class));
highAvailabilityManager.scheduleRestartForVmsOnHost(hostVO, true);
}