Merge release branch 4.20 to main

* 4.20:
  VR: fix site-2-site VPN if split connections is enabled (#10067)
  UI: fix cannot open 'Edit tags' modal for static routes (#10065)
  Update ownership selection component to be language independent (#10052)
  Support to enable/disable VM High Availability manager and related alerts (#10118)
This commit is contained in:
Daan Hoogland 2024-12-30 13:35:30 +01:00
commit 2daffa34f2
12 changed files with 297 additions and 37 deletions

View File

@ -32,7 +32,7 @@ import java.util.List;
*/ */
public interface HighAvailabilityManager extends Manager { public interface HighAvailabilityManager extends Manager {
public ConfigKey<Boolean> ForceHA = new ConfigKey<>("Advanced", Boolean.class, "force.ha", "false", ConfigKey<Boolean> ForceHA = new ConfigKey<>("Advanced", Boolean.class, "force.ha", "false",
"Force High-Availability to happen even if the VM says no.", true, Cluster); "Force High-Availability to happen even if the VM says no.", true, Cluster);
ConfigKey<Integer> HAWorkers = new ConfigKey<>("Advanced", Integer.class, "ha.workers", "5", ConfigKey<Integer> HAWorkers = new ConfigKey<>("Advanced", Integer.class, "ha.workers", "5",
@ -112,7 +112,7 @@ public interface HighAvailabilityManager extends Manager {
void cancelDestroy(VMInstanceVO vm, Long hostId); void cancelDestroy(VMInstanceVO vm, Long hostId);
void scheduleDestroy(VMInstanceVO vm, long hostId); boolean scheduleDestroy(VMInstanceVO vm, long hostId);
/** /**
* Schedule restarts for all vms running on the host. * Schedule restarts for all vms running on the host.
@ -143,7 +143,7 @@ public interface HighAvailabilityManager extends Manager {
* @param host host the virtual machine is on. * @param host host the virtual machine is on.
* @param type which type of stop is requested. * @param type which type of stop is requested.
*/ */
void scheduleStop(VMInstanceVO vm, long hostId, WorkType type); boolean scheduleStop(VMInstanceVO vm, long hostId, WorkType type);
void cancelScheduledMigrations(HostVO host); void cancelScheduledMigrations(HostVO host);

View File

@ -16,6 +16,8 @@
// under the License. // under the License.
package com.cloud.ha; package com.cloud.ha;
import static org.apache.cloudstack.framework.config.ConfigKey.Scope.Zone;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
@ -121,6 +123,16 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements Configur
"Total number of attempts for trying migration of a VM.", "Total number of attempts for trying migration of a VM.",
true, ConfigKey.Scope.Global); true, ConfigKey.Scope.Global);
public static ConfigKey<Boolean> VmHaEnabled = new ConfigKey<>("Advanced", Boolean.class, "vm.ha.enabled", "true",
"Enable/Disable VM High Availability manager, it is enabled by default."
+ " When enabled, the VM HA WorkItems (for VM Stop, Restart, Migration, Destroy) can be created and the scheduled items are executed; and"
+ " When disabled, new VM HA WorkItems are not allowed and the scheduled items are retried until max retries configured at 'vm.ha.migration.max.retries'"
+ " (executed in case HA is re-enabled during retry attempts), and then purged after 'time.between.failures' by the cleanup thread that runs"
+ " regularly at 'time.between.cleanup'", true, Zone);
protected static ConfigKey<Boolean> VmHaAlertsEnabled = new ConfigKey<>("Advanced", Boolean.class, "vm.ha.alerts.enabled", "true",
"Enable/Disable alerts for the VM HA operations, it is enabled by default.", true, Zone);
WorkerThread[] _workers; WorkerThread[] _workers;
boolean _stopped; boolean _stopped;
long _timeToSleep; long _timeToSleep;
@ -185,7 +197,6 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements Configur
_haPlanners = haPlanners; _haPlanners = haPlanners;
} }
@Inject @Inject
AgentManager _agentMgr; AgentManager _agentMgr;
@Inject @Inject
@ -231,6 +242,15 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements Configur
return Status.Alert; return Status.Alert;
} }
if (!VmHaEnabled.valueIn(host.getDataCenterId())) {
String message = String.format("Unable to investigate the host %s (%d), VM high availability manager is disabled.", host.getName(), hostId);
if (logger.isDebugEnabled()) {
logger.debug(message);
}
sendHostAlert(host, message);
return Status.Alert;
}
Status hostState = null; Status hostState = null;
for (Investigator investigator : investigators) { for (Investigator investigator : investigators) {
hostState = investigator.isAgentAlive(host); hostState = investigator.isAgentAlive(host);
@ -260,6 +280,15 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements Configur
return; return;
} }
if (!VmHaEnabled.valueIn(host.getDataCenterId())) {
String message = String.format("Unable to schedule restart for VMs on host %s (%d), VM high availability manager is disabled.", host.getName(), host.getId());
if (logger.isDebugEnabled()) {
logger.debug(message);
}
sendHostAlert(host, message);
return;
}
logger.warn("Scheduling restart for VMs on host " + host.getId() + "-" + host.getName()); logger.warn("Scheduling restart for VMs on host " + host.getId() + "-" + host.getName());
final List<VMInstanceVO> vms = _instanceDao.listByHostId(host.getId()); final List<VMInstanceVO> vms = _instanceDao.listByHostId(host.getId());
@ -314,12 +343,21 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements Configur
} }
@Override @Override
public void scheduleStop(VMInstanceVO vm, long hostId, WorkType type) { public boolean scheduleStop(VMInstanceVO vm, long hostId, WorkType type) {
assert (type == WorkType.CheckStop || type == WorkType.ForceStop || type == WorkType.Stop); assert (type == WorkType.CheckStop || type == WorkType.ForceStop || type == WorkType.Stop);
if (_haDao.hasBeenScheduled(vm.getId(), type)) { if (_haDao.hasBeenScheduled(vm.getId(), type)) {
logger.info("There's already a job scheduled to stop " + vm); logger.info("There's already a job scheduled to stop " + vm);
return; return false;
}
if (!VmHaEnabled.valueIn(vm.getDataCenterId())) {
String message = String.format("Unable to schedule stop for the VM %s (%d) on host %d, VM high availability manager is disabled.", vm.getName(), vm.getId(), hostId);
if (logger.isDebugEnabled()) {
logger.debug(message);
}
sendVMAlert(vm, message);
return false;
} }
HaWorkVO work = new HaWorkVO(vm.getId(), vm.getType(), type, Step.Scheduled, hostId, vm.getState(), 0, vm.getUpdated()); HaWorkVO work = new HaWorkVO(vm.getId(), vm.getType(), type, Step.Scheduled, hostId, vm.getState(), 0, vm.getUpdated());
@ -328,6 +366,7 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements Configur
logger.debug("Scheduled " + work); logger.debug("Scheduled " + work);
} }
wakeupWorkers(); wakeupWorkers();
return true;
} }
protected void wakeupWorkers() { protected void wakeupWorkers() {
@ -339,17 +378,37 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements Configur
@Override @Override
public boolean scheduleMigration(final VMInstanceVO vm) { public boolean scheduleMigration(final VMInstanceVO vm) {
if (vm.getHostId() != null) { if (vm.getHostId() == null) {
return false;
}
if (!VmHaEnabled.valueIn(vm.getDataCenterId())) {
String message = String.format("Unable to schedule migration for the VM %s (%d) on host %d, VM high availability manager is disabled.", vm.getName(), vm.getId(), vm.getHostId());
if (logger.isDebugEnabled()) {
logger.debug(message);
}
sendVMAlert(vm, message);
return false;
}
final HaWorkVO work = new HaWorkVO(vm.getId(), vm.getType(), WorkType.Migration, Step.Scheduled, vm.getHostId(), vm.getState(), 0, vm.getUpdated()); final HaWorkVO work = new HaWorkVO(vm.getId(), vm.getType(), WorkType.Migration, Step.Scheduled, vm.getHostId(), vm.getState(), 0, vm.getUpdated());
_haDao.persist(work); _haDao.persist(work);
logger.info("Scheduled migration work of VM " + vm.getUuid() + " from host " + _hostDao.findById(vm.getHostId()) + " with HAWork " + work); logger.info("Scheduled migration work of VM " + vm.getUuid() + " from host " + _hostDao.findById(vm.getHostId()) + " with HAWork " + work);
wakeupWorkers(); wakeupWorkers();
}
return true; return true;
} }
@Override @Override
public void scheduleRestart(VMInstanceVO vm, boolean investigate) { public void scheduleRestart(VMInstanceVO vm, boolean investigate) {
if (!VmHaEnabled.valueIn(vm.getDataCenterId())) {
String message = String.format("Unable to schedule restart for the VM %s (%d), VM high availability manager is disabled.", vm.getName(), vm.getId());
if (logger.isDebugEnabled()) {
logger.debug(message);
}
sendVMAlert(vm, message);
return;
}
logger.debug("HA schedule restart"); logger.debug("HA schedule restart");
Long hostId = vm.getHostId(); Long hostId = vm.getHostId();
if (hostId == null) { if (hostId == null) {
@ -440,7 +499,6 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements Configur
} }
wakeupWorkers(); wakeupWorkers();
} }
private void startVm(VirtualMachine vm, Map<VirtualMachineProfile.Param, Object> params, private void startVm(VirtualMachine vm, Map<VirtualMachineProfile.Param, Object> params,
@ -737,13 +795,23 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements Configur
} }
@Override @Override
public void scheduleDestroy(VMInstanceVO vm, long hostId) { public boolean scheduleDestroy(VMInstanceVO vm, long hostId) {
if (!VmHaEnabled.valueIn(vm.getDataCenterId())) {
String message = String.format("Unable to schedule destroy for the VM %s (%d) on host %d, VM high availability manager is disabled.", vm.getName(), vm.getId(), hostId);
if (logger.isDebugEnabled()) {
logger.debug(message);
}
sendVMAlert(vm, message);
return false;
}
final HaWorkVO work = new HaWorkVO(vm.getId(), vm.getType(), WorkType.Destroy, Step.Scheduled, hostId, vm.getState(), 0, vm.getUpdated()); final HaWorkVO work = new HaWorkVO(vm.getId(), vm.getType(), WorkType.Destroy, Step.Scheduled, hostId, vm.getState(), 0, vm.getUpdated());
_haDao.persist(work); _haDao.persist(work);
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("Scheduled " + work.toString()); logger.debug("Scheduled " + work.toString());
} }
wakeupWorkers(); wakeupWorkers();
return true;
} }
@Override @Override
@ -892,7 +960,17 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements Configur
private void processWork(final HaWorkVO work) { private void processWork(final HaWorkVO work) {
final WorkType wt = work.getWorkType(); final WorkType wt = work.getWorkType();
final VMInstanceVO vm = _instanceDao.findById(work.getInstanceId());
try { try {
if (vm != null && !VmHaEnabled.valueIn(vm.getDataCenterId())) {
if (logger.isDebugEnabled()) {
logger.debug(String.format("VM high availability manager is disabled, rescheduling the HA work %s, for the VM %s (id) to retry later in case VM high availability manager is enabled on retry attempt", work, vm.getName(), vm.getId()));
}
long nextTime = getRescheduleTime(wt);
rescheduleWork(work, nextTime);
return;
}
Long nextTime = null; Long nextTime = null;
if (wt == WorkType.Migration) { if (wt == WorkType.Migration) {
nextTime = migrate(work); nextTime = migrate(work);
@ -921,9 +999,10 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements Configur
// if restart failed in the middle due to exception, VM state may has been changed // if restart failed in the middle due to exception, VM state may has been changed
// recapture into the HA worker so that it can really continue in it next turn // recapture into the HA worker so that it can really continue in it next turn
VMInstanceVO vm = _instanceDao.findById(work.getInstanceId()); if (vm != null) {
work.setUpdateTime(vm.getUpdated()); work.setUpdateTime(vm.getUpdated());
work.setPreviousState(vm.getState()); work.setPreviousState(vm.getState());
}
} finally { } finally {
if (!Step.Done.equals(work.getStep())) { if (!Step.Done.equals(work.getStep())) {
if (work.getTimesTried() >= _maxRetries) { if (work.getTimesTried() >= _maxRetries) {
@ -1128,11 +1207,33 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements Configur
public ConfigKey<?>[] getConfigKeys() { public ConfigKey<?>[] getConfigKeys() {
return new ConfigKey[] {TimeBetweenCleanup, MigrationMaxRetries, TimeToSleep, TimeBetweenFailures, return new ConfigKey[] {TimeBetweenCleanup, MigrationMaxRetries, TimeToSleep, TimeBetweenFailures,
StopRetryInterval, RestartRetryInterval, MigrateRetryInterval, InvestigateRetryInterval, StopRetryInterval, RestartRetryInterval, MigrateRetryInterval, InvestigateRetryInterval,
HAWorkers, ForceHA, KvmHAFenceHostIfHeartbeatFailsOnStorage}; HAWorkers, ForceHA, VmHaEnabled, VmHaAlertsEnabled, KvmHAFenceHostIfHeartbeatFailsOnStorage};
} }
@Override @Override
public int expungeWorkItemsByVmList(List<Long> vmIds, Long batchSize) { public int expungeWorkItemsByVmList(List<Long> vmIds, Long batchSize) {
return _haDao.expungeByVmList(vmIds, batchSize); return _haDao.expungeByVmList(vmIds, batchSize);
} }
private void sendVMAlert(VMInstanceVO vm, String message) {
if (vm == null || !VmHaAlertsEnabled.valueIn(vm.getDataCenterId())) {
return;
}
AlertManager.AlertType alertType = AlertManager.AlertType.ALERT_TYPE_USERVM;
if (VirtualMachine.Type.DomainRouter.equals(vm.getType())) {
alertType = AlertManager.AlertType.ALERT_TYPE_DOMAIN_ROUTER;
} else if (VirtualMachine.Type.ConsoleProxy.equals(vm.getType())) {
alertType = AlertManager.AlertType.ALERT_TYPE_CONSOLE_PROXY;
} else if (VirtualMachine.Type.SecondaryStorageVm.equals(vm.getType())) {
alertType = AlertManager.AlertType.ALERT_TYPE_SSVM;
}
_alertMgr.sendAlert(alertType, vm.getDataCenterId(), vm.getPodIdToDeployIn(), message, message);
}
private void sendHostAlert(HostVO host, String message) {
if (host == null || !VmHaAlertsEnabled.valueIn(host.getDataCenterId())) {
return;
}
_alertMgr.sendAlert(AlertManager.AlertType.ALERT_TYPE_HOST, host.getDataCenterId(), host.getPodId(), message, message);
}
} }

View File

@ -41,6 +41,7 @@ import com.cloud.alert.AlertManager;
import com.cloud.cpu.CPU; import com.cloud.cpu.CPU;
import com.cloud.exception.StorageConflictException; import com.cloud.exception.StorageConflictException;
import com.cloud.exception.StorageUnavailableException; import com.cloud.exception.StorageUnavailableException;
import com.cloud.ha.HighAvailabilityManagerImpl;
import com.cloud.host.HostTagVO; import com.cloud.host.HostTagVO;
import com.cloud.storage.Volume; import com.cloud.storage.Volume;
import com.cloud.storage.VolumeVO; import com.cloud.storage.VolumeVO;
@ -1363,6 +1364,11 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
throw new CloudRuntimeException("Cannot perform maintain when resource state is " + hostState + ", hostId = " + hostId); throw new CloudRuntimeException("Cannot perform maintain when resource state is " + hostState + ", hostId = " + hostId);
} }
final List<VMInstanceVO> vms = _vmDao.listByHostId(hostId);
if (CollectionUtils.isNotEmpty(vms) && !HighAvailabilityManagerImpl.VmHaEnabled.valueIn(host.getDataCenterId())) {
throw new CloudRuntimeException(String.format("Cannot perform maintain for the host %s (%d) as there are running VMs on it and VM high availability manager is disabled", host.getName(), hostId));
}
final MaintainAnswer answer = (MaintainAnswer)_agentMgr.easySend(hostId, new MaintainCommand()); final MaintainAnswer answer = (MaintainAnswer)_agentMgr.easySend(hostId, new MaintainCommand());
if (answer == null || !answer.getResult()) { if (answer == null || !answer.getResult()) {
logger.warn("Unable to send MaintainCommand to host: " + hostId); logger.warn("Unable to send MaintainCommand to host: " + hostId);
@ -1382,8 +1388,6 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
/* TODO: move below to listener */ /* TODO: move below to listener */
if (host.getType() == Host.Type.Routing) { if (host.getType() == Host.Type.Routing) {
final List<VMInstanceVO> vms = _vmDao.listByHostId(hostId);
if (vms.size() == 0) { if (vms.size() == 0) {
return true; return true;
} }

View File

@ -16,6 +16,7 @@
// under the License. // under the License.
package com.cloud.ha; package com.cloud.ha;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
@ -32,6 +33,7 @@ import javax.inject.Inject;
import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService; import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProviderManager; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProviderManager;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.managed.context.ManagedContext; import org.apache.cloudstack.managed.context.ManagedContext;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
@ -174,10 +176,15 @@ public class HighAvailabilityManagerImplTest {
public void scheduleRestartForVmsOnHost() { public void scheduleRestartForVmsOnHost() {
Mockito.when(hostVO.getType()).thenReturn(Host.Type.Routing); Mockito.when(hostVO.getType()).thenReturn(Host.Type.Routing);
Mockito.when(hostVO.getHypervisorType()).thenReturn(HypervisorType.KVM); Mockito.when(hostVO.getHypervisorType()).thenReturn(HypervisorType.KVM);
Mockito.when(hostVO.getDataCenterId()).thenReturn(1L);
Mockito.lenient().when(_instanceDao.listByHostId(42l)).thenReturn(Arrays.asList(Mockito.mock(VMInstanceVO.class))); Mockito.lenient().when(_instanceDao.listByHostId(42l)).thenReturn(Arrays.asList(Mockito.mock(VMInstanceVO.class)));
Mockito.when(_podDao.findById(Mockito.anyLong())).thenReturn(Mockito.mock(HostPodVO.class)); Mockito.when(_podDao.findById(Mockito.anyLong())).thenReturn(Mockito.mock(HostPodVO.class));
Mockito.when(_dcDao.findById(Mockito.anyLong())).thenReturn(Mockito.mock(DataCenterVO.class)); Mockito.when(_dcDao.findById(Mockito.anyLong())).thenReturn(Mockito.mock(DataCenterVO.class));
ConfigKey<Boolean> haEnabled = Mockito.mock(ConfigKey.class);
highAvailabilityManager.VmHaEnabled = haEnabled;
Mockito.when(highAvailabilityManager.VmHaEnabled.valueIn(1L)).thenReturn(true);
highAvailabilityManager.scheduleRestartForVmsOnHost(hostVO, true); highAvailabilityManager.scheduleRestartForVmsOnHost(hostVO, true);
} }
@ -189,11 +196,25 @@ public class HighAvailabilityManagerImplTest {
highAvailabilityManager.scheduleRestartForVmsOnHost(hostVO, true); highAvailabilityManager.scheduleRestartForVmsOnHost(hostVO, true);
} }
@Test
public void scheduleRestartForVmsOnHostHADisabled() {
Mockito.when(hostVO.getType()).thenReturn(Host.Type.Routing);
Mockito.when(hostVO.getHypervisorType()).thenReturn(HypervisorType.KVM);
Mockito.when(hostVO.getDataCenterId()).thenReturn(1L);
ConfigKey<Boolean> haEnabled = Mockito.mock(ConfigKey.class);
highAvailabilityManager.VmHaEnabled = haEnabled;
Mockito.when(highAvailabilityManager.VmHaEnabled.valueIn(1L)).thenReturn(false);
highAvailabilityManager.scheduleRestartForVmsOnHost(hostVO, true);
}
@Test @Test
public void scheduleRestartForVmsOnHostNonEmptyVMList() { public void scheduleRestartForVmsOnHostNonEmptyVMList() {
Mockito.when(hostVO.getId()).thenReturn(1l); Mockito.when(hostVO.getId()).thenReturn(1l);
Mockito.when(hostVO.getType()).thenReturn(Host.Type.Routing); Mockito.when(hostVO.getType()).thenReturn(Host.Type.Routing);
Mockito.when(hostVO.getHypervisorType()).thenReturn(HypervisorType.XenServer); Mockito.when(hostVO.getHypervisorType()).thenReturn(HypervisorType.XenServer);
Mockito.when(hostVO.getDataCenterId()).thenReturn(1L);
List<VMInstanceVO> vms = new ArrayList<VMInstanceVO>(); List<VMInstanceVO> vms = new ArrayList<VMInstanceVO>();
VMInstanceVO vm1 = Mockito.mock(VMInstanceVO.class); VMInstanceVO vm1 = Mockito.mock(VMInstanceVO.class);
Mockito.lenient().when(vm1.getHostId()).thenReturn(1l); Mockito.lenient().when(vm1.getHostId()).thenReturn(1l);
@ -206,6 +227,7 @@ public class HighAvailabilityManagerImplTest {
//Mockito.when(vm2.getInstanceName()).thenReturn("r-2-VM"); //Mockito.when(vm2.getInstanceName()).thenReturn("r-2-VM");
Mockito.when(vm2.getType()).thenReturn(VirtualMachine.Type.DomainRouter); Mockito.when(vm2.getType()).thenReturn(VirtualMachine.Type.DomainRouter);
Mockito.when(vm2.isHaEnabled()).thenReturn(true); Mockito.when(vm2.isHaEnabled()).thenReturn(true);
Mockito.when(vm2.getDataCenterId()).thenReturn(1L);
vms.add(vm2); vms.add(vm2);
Mockito.when(_instanceDao.listByHostId(Mockito.anyLong())).thenReturn(vms); Mockito.when(_instanceDao.listByHostId(Mockito.anyLong())).thenReturn(vms);
Mockito.when(_instanceDao.findByUuid(vm1.getUuid())).thenReturn(vm1); Mockito.when(_instanceDao.findByUuid(vm1.getUuid())).thenReturn(vm1);
@ -216,12 +238,125 @@ public class HighAvailabilityManagerImplTest {
Mockito.when(_haDao.persist((HaWorkVO)Mockito.any())).thenReturn(Mockito.mock(HaWorkVO.class)); Mockito.when(_haDao.persist((HaWorkVO)Mockito.any())).thenReturn(Mockito.mock(HaWorkVO.class));
Mockito.when(_serviceOfferingDao.findById(vm1.getServiceOfferingId())).thenReturn(Mockito.mock(ServiceOfferingVO.class)); Mockito.when(_serviceOfferingDao.findById(vm1.getServiceOfferingId())).thenReturn(Mockito.mock(ServiceOfferingVO.class));
ConfigKey<Boolean> haEnabled = Mockito.mock(ConfigKey.class);
highAvailabilityManager.VmHaEnabled = haEnabled;
Mockito.when(highAvailabilityManager.VmHaEnabled.valueIn(1L)).thenReturn(true);
highAvailabilityManager.scheduleRestartForVmsOnHost(hostVO, true); highAvailabilityManager.scheduleRestartForVmsOnHost(hostVO, true);
} }
@Test
public void scheduleRestartHADisabled() {
VMInstanceVO vm = Mockito.mock(VMInstanceVO.class);
Mockito.when(vm.getId()).thenReturn(1L);
Mockito.when(vm.getDataCenterId()).thenReturn(1L);
ConfigKey<Boolean> haEnabled = Mockito.mock(ConfigKey.class);
highAvailabilityManager.VmHaEnabled = haEnabled;
Mockito.when(highAvailabilityManager.VmHaEnabled.valueIn(1L)).thenReturn(false);
highAvailabilityManager.scheduleRestart(vm, true);
}
@Test
public void scheduleRestartHostNotSupported() {
VMInstanceVO vm = Mockito.mock(VMInstanceVO.class);
Mockito.when(vm.getDataCenterId()).thenReturn(1L);
Mockito.when(vm.getHostId()).thenReturn(1L);
Mockito.when(vm.getHypervisorType()).thenReturn(HypervisorType.VMware);
highAvailabilityManager.scheduleRestart(vm, true);
}
@Test
public void scheduleStop() {
VMInstanceVO vm = Mockito.mock(VMInstanceVO.class);
Mockito.when(vm.getId()).thenReturn(1L);
Mockito.when(vm.getDataCenterId()).thenReturn(1L);
Mockito.when(vm.getType()).thenReturn(VirtualMachine.Type.User);
Mockito.when(vm.getState()).thenReturn(VirtualMachine.State.Running);
Mockito.when(_haDao.hasBeenScheduled(vm.getId(), WorkType.Stop)).thenReturn(false);
Mockito.when(_haDao.persist((HaWorkVO)Mockito.any())).thenReturn(Mockito.mock(HaWorkVO.class));
ConfigKey<Boolean> haEnabled = Mockito.mock(ConfigKey.class);
highAvailabilityManager.VmHaEnabled = haEnabled;
Mockito.when(highAvailabilityManager.VmHaEnabled.valueIn(1L)).thenReturn(true);
assertTrue(highAvailabilityManager.scheduleStop(vm, 1L, WorkType.Stop));
}
@Test
public void scheduleStopHADisabled() {
VMInstanceVO vm = Mockito.mock(VMInstanceVO.class);
Mockito.when(vm.getId()).thenReturn(1L);
Mockito.when(vm.getDataCenterId()).thenReturn(1L);
Mockito.when(_haDao.hasBeenScheduled(vm.getId(), WorkType.Stop)).thenReturn(false);
ConfigKey<Boolean> haEnabled = Mockito.mock(ConfigKey.class);
highAvailabilityManager.VmHaEnabled = haEnabled;
Mockito.when(highAvailabilityManager.VmHaEnabled.valueIn(1L)).thenReturn(false);
assertFalse(highAvailabilityManager.scheduleStop(vm, 1L, WorkType.Stop));
}
@Test
public void scheduleMigration() {
VMInstanceVO vm = Mockito.mock(VMInstanceVO.class);
Mockito.when(vm.getId()).thenReturn(1L);
Mockito.when(vm.getDataCenterId()).thenReturn(1L);
Mockito.when(vm.getType()).thenReturn(VirtualMachine.Type.User);
Mockito.when(vm.getState()).thenReturn(VirtualMachine.State.Running);
Mockito.when(vm.getHostId()).thenReturn(1L);
Mockito.when(_haDao.persist((HaWorkVO)Mockito.any())).thenReturn(Mockito.mock(HaWorkVO.class));
ConfigKey<Boolean> haEnabled = Mockito.mock(ConfigKey.class);
highAvailabilityManager.VmHaEnabled = haEnabled;
Mockito.when(highAvailabilityManager.VmHaEnabled.valueIn(1L)).thenReturn(true);
assertTrue(highAvailabilityManager.scheduleMigration(vm));
}
@Test
public void scheduleMigrationHADisabled() {
VMInstanceVO vm = Mockito.mock(VMInstanceVO.class);
Mockito.when(vm.getHostId()).thenReturn(1L);
Mockito.when(vm.getDataCenterId()).thenReturn(1L);
ConfigKey<Boolean> haEnabled = Mockito.mock(ConfigKey.class);
highAvailabilityManager.VmHaEnabled = haEnabled;
Mockito.when(highAvailabilityManager.VmHaEnabled.valueIn(1L)).thenReturn(false);
assertFalse(highAvailabilityManager.scheduleMigration(vm));
}
@Test
public void scheduleDestroy() {
VMInstanceVO vm = Mockito.mock(VMInstanceVO.class);
Mockito.when(vm.getId()).thenReturn(1L);
Mockito.when(vm.getDataCenterId()).thenReturn(1L);
Mockito.when(vm.getType()).thenReturn(VirtualMachine.Type.User);
Mockito.when(vm.getState()).thenReturn(VirtualMachine.State.Running);
Mockito.when(_haDao.persist((HaWorkVO)Mockito.any())).thenReturn(Mockito.mock(HaWorkVO.class));
assertTrue(highAvailabilityManager.scheduleDestroy(vm, 1L));
}
@Test
public void scheduleDestroyHADisabled() {
VMInstanceVO vm = Mockito.mock(VMInstanceVO.class);
Mockito.when(vm.getDataCenterId()).thenReturn(1L);
ConfigKey<Boolean> haEnabled = Mockito.mock(ConfigKey.class);
highAvailabilityManager.VmHaEnabled = haEnabled;
Mockito.when(highAvailabilityManager.VmHaEnabled.valueIn(1L)).thenReturn(false);
assertFalse(highAvailabilityManager.scheduleDestroy(vm, 1L));
}
@Test @Test
public void investigateHostStatusSuccess() { public void investigateHostStatusSuccess() {
Mockito.when(_hostDao.findById(Mockito.anyLong())).thenReturn(hostVO); Mockito.when(_hostDao.findById(Mockito.anyLong())).thenReturn(hostVO);
Mockito.when(hostVO.getDataCenterId()).thenReturn(1L);
// Set the list of investigators, CheckOnAgentInvestigator suffices for now // Set the list of investigators, CheckOnAgentInvestigator suffices for now
Investigator investigator = Mockito.mock(CheckOnAgentInvestigator.class); Investigator investigator = Mockito.mock(CheckOnAgentInvestigator.class);
List<Investigator> investigators = new ArrayList<Investigator>(); List<Investigator> investigators = new ArrayList<Investigator>();
@ -230,12 +365,17 @@ public class HighAvailabilityManagerImplTest {
// Mock isAgentAlive to return host status as Down // Mock isAgentAlive to return host status as Down
Mockito.when(investigator.isAgentAlive(hostVO)).thenReturn(Status.Down); Mockito.when(investigator.isAgentAlive(hostVO)).thenReturn(Status.Down);
ConfigKey<Boolean> haEnabled = Mockito.mock(ConfigKey.class);
highAvailabilityManager.VmHaEnabled = haEnabled;
Mockito.when(highAvailabilityManager.VmHaEnabled.valueIn(1L)).thenReturn(true);
assertTrue(highAvailabilityManager.investigate(1l) == Status.Down); assertTrue(highAvailabilityManager.investigate(1l) == Status.Down);
} }
@Test @Test
public void investigateHostStatusFailure() { public void investigateHostStatusFailure() {
Mockito.when(_hostDao.findById(Mockito.anyLong())).thenReturn(hostVO); Mockito.when(_hostDao.findById(Mockito.anyLong())).thenReturn(hostVO);
Mockito.when(hostVO.getDataCenterId()).thenReturn(1L);
// Set the list of investigators, CheckOnAgentInvestigator suffices for now // Set the list of investigators, CheckOnAgentInvestigator suffices for now
// Also no need to mock isAgentAlive() as actual implementation returns null // Also no need to mock isAgentAlive() as actual implementation returns null
Investigator investigator = Mockito.mock(CheckOnAgentInvestigator.class); Investigator investigator = Mockito.mock(CheckOnAgentInvestigator.class);
@ -243,9 +383,25 @@ public class HighAvailabilityManagerImplTest {
investigators.add(investigator); investigators.add(investigator);
highAvailabilityManager.setInvestigators(investigators); highAvailabilityManager.setInvestigators(investigators);
ConfigKey<Boolean> haEnabled = Mockito.mock(ConfigKey.class);
highAvailabilityManager.VmHaEnabled = haEnabled;
Mockito.when(highAvailabilityManager.VmHaEnabled.valueIn(1L)).thenReturn(true);
assertNull(highAvailabilityManager.investigate(1l)); assertNull(highAvailabilityManager.investigate(1l));
} }
@Test
public void investigateHostStatusHADisabled() {
Mockito.when(_hostDao.findById(Mockito.anyLong())).thenReturn(hostVO);
Mockito.when(hostVO.getDataCenterId()).thenReturn(1L);
ConfigKey<Boolean> haEnabled = Mockito.mock(ConfigKey.class);
highAvailabilityManager.VmHaEnabled = haEnabled;
Mockito.when(highAvailabilityManager.VmHaEnabled.valueIn(1L)).thenReturn(false);
assertTrue(highAvailabilityManager.investigate(1L) == Status.Alert);
}
private void processWorkWithRetryCount(int count, Step expectedStep) { private void processWorkWithRetryCount(int count, Step expectedStep) {
assertNotNull(processWorkMethod); assertNotNull(processWorkMethod);
HaWorkVO work = new HaWorkVO(1l, VirtualMachine.Type.User, WorkType.Migration, Step.Scheduled, 1l, VirtualMachine.State.Running, count, 12345678l); HaWorkVO work = new HaWorkVO(1l, VirtualMachine.Type.User, WorkType.Migration, Step.Scheduled, 1l, VirtualMachine.State.Running, count, 12345678l);

View File

@ -1100,7 +1100,7 @@ class CsSite2SiteVpn(CsDataBag):
file.addeq(" dpddelay=30") file.addeq(" dpddelay=30")
file.addeq(" dpdtimeout=120") file.addeq(" dpdtimeout=120")
file.addeq(" dpdaction=restart") file.addeq(" dpdaction=restart")
if splitconnections and peerlistarr.count > 1: if splitconnections and len(peerlistarr) > 1:
logging.debug('Splitting connections for rightsubnets %s' % peerlistarr) logging.debug('Splitting connections for rightsubnets %s' % peerlistarr)
for peeridx in range(1, len(peerlistarr)): for peeridx in range(1, len(peerlistarr)):
logging.debug('Adding split connection -%d for subnet %s' % (peeridx + 1, peerlistarr[peeridx])) logging.debug('Adding split connection -%d for subnet %s' % (peeridx + 1, peerlistarr[peeridx]))

View File

@ -2312,14 +2312,14 @@ export default {
domainid: store.getters.userInfo.domainid, domainid: store.getters.userInfo.domainid,
account: store.getters.userInfo.account account: store.getters.userInfo.account
} }
if (OwnerOptions.selectedAccountType === this.$t('label.account')) { if (OwnerOptions.selectedAccountType === 'Account') {
if (!OwnerOptions.selectedAccount) { if (!OwnerOptions.selectedAccount) {
return return
} }
this.owner.account = OwnerOptions.selectedAccount this.owner.account = OwnerOptions.selectedAccount
this.owner.domainid = OwnerOptions.selectedDomain this.owner.domainid = OwnerOptions.selectedDomain
this.owner.projectid = null this.owner.projectid = null
} else if (OwnerOptions.selectedAccountType === this.$t('label.project')) { } else if (OwnerOptions.selectedAccountType === 'Project') {
if (!OwnerOptions.selectedProject) { if (!OwnerOptions.selectedProject) {
return return
} }

View File

@ -31,8 +31,8 @@
} }
" "
> >
<a-select-option :value="$t('label.account')">{{ $t('label.account') }}</a-select-option> <a-select-option :value="'Account'">{{ $t('label.account') }}</a-select-option>
<a-select-option :value="$t('label.project')">{{ $t('label.project') }}</a-select-option> <a-select-option :value="'Project'">{{ $t('label.project') }}</a-select-option>
</a-select> </a-select>
</a-form-item> </a-form-item>
<a-form-item :label="$t('label.domain')" required> <a-form-item :label="$t('label.domain')" required>
@ -67,7 +67,7 @@
</a-select> </a-select>
</a-form-item> </a-form-item>
<template v-if="selectedAccountType === $t('label.account')"> <template v-if="selectedAccountType === 'Account'">
<a-form-item :label="$t('label.account')" required> <a-form-item :label="$t('label.account')" required>
<a-select <a-select
@change="emitChangeEvent" @change="emitChangeEvent"
@ -139,7 +139,7 @@ export default {
domains: [], domains: [],
accounts: [], accounts: [],
projects: [], projects: [],
selectedAccountType: this.$store.getters.project?.id ? this.$t('label.project') : this.$t('label.account'), selectedAccountType: this.$store.getters.project?.id ? 'Project' : 'Account',
selectedDomain: null, selectedDomain: null,
selectedAccount: null, selectedAccount: null,
selectedProject: null, selectedProject: null,
@ -243,7 +243,7 @@ export default {
}) })
}, },
changeDomain () { changeDomain () {
if (this.selectedAccountType === this.$t('label.account')) { if (this.selectedAccountType === 'Account') {
this.fetchAccounts() this.fetchAccounts()
} else { } else {
this.fetchProjects() this.fetchProjects()

View File

@ -492,14 +492,14 @@ export default {
domainid: this.$store.getters.userInfo.domainid, domainid: this.$store.getters.userInfo.domainid,
account: this.$store.getters.userInfo.account account: this.$store.getters.userInfo.account
} }
if (OwnerOptions.selectedAccountType === this.$t('label.account')) { if (OwnerOptions.selectedAccountType === 'Account') {
if (!OwnerOptions.selectedAccount) { if (!OwnerOptions.selectedAccount) {
return return
} }
this.owner.account = OwnerOptions.selectedAccount this.owner.account = OwnerOptions.selectedAccount
this.owner.domainid = OwnerOptions.selectedDomain this.owner.domainid = OwnerOptions.selectedDomain
this.owner.projectid = null this.owner.projectid = null
} else if (OwnerOptions.selectedAccountType === this.$t('label.project')) { } else if (OwnerOptions.selectedAccountType === 'Project') {
if (!OwnerOptions.selectedProject) { if (!OwnerOptions.selectedProject) {
return return
} }

View File

@ -294,14 +294,14 @@ export default {
domainid: this.$store.getters.userInfo.domainid, domainid: this.$store.getters.userInfo.domainid,
account: this.$store.getters.userInfo.account account: this.$store.getters.userInfo.account
} }
if (OwnerOptions.selectedAccountType === this.$t('label.account')) { if (OwnerOptions.selectedAccountType === 'Account') {
if (!OwnerOptions.selectedAccount) { if (!OwnerOptions.selectedAccount) {
return return
} }
this.owner.account = OwnerOptions.selectedAccount this.owner.account = OwnerOptions.selectedAccount
this.owner.domainid = OwnerOptions.selectedDomain this.owner.domainid = OwnerOptions.selectedDomain
this.owner.projectid = null this.owner.projectid = null
} else if (OwnerOptions.selectedAccountType === this.$t('label.project')) { } else if (OwnerOptions.selectedAccountType === 'Project') {
if (!OwnerOptions.selectedProject) { if (!OwnerOptions.selectedProject) {
return return
} }

View File

@ -304,7 +304,6 @@ export default {
}, },
openTagsModal (route) { openTagsModal (route) {
this.selectedRule = route this.selectedRule = route
this.rulesRef.value.resetFields()
this.fetchTags(this.selectedRule) this.fetchTags(this.selectedRule)
this.tagsModalVisible = true this.tagsModalVisible = true
} }

View File

@ -273,14 +273,14 @@ export default {
fetchOwnerOptions (OwnerOptions) { fetchOwnerOptions (OwnerOptions) {
this.owner = {} this.owner = {}
console.log('fetching owner') console.log('fetching owner')
if (OwnerOptions.selectedAccountType === this.$t('label.account')) { if (OwnerOptions.selectedAccountType === 'Account') {
if (!OwnerOptions.selectedAccount) { if (!OwnerOptions.selectedAccount) {
return return
} }
console.log('fetched account') console.log('fetched account')
this.owner.account = OwnerOptions.selectedAccount this.owner.account = OwnerOptions.selectedAccount
this.owner.domainid = OwnerOptions.selectedDomain this.owner.domainid = OwnerOptions.selectedDomain
} else if (OwnerOptions.selectedAccountType === this.$t('label.project')) { } else if (OwnerOptions.selectedAccountType === 'Project') {
if (!OwnerOptions.selectedProject) { if (!OwnerOptions.selectedProject) {
return return
} }

View File

@ -211,13 +211,13 @@ export default {
}, },
fetchOwnerOptions (OwnerOptions) { fetchOwnerOptions (OwnerOptions) {
this.owner = {} this.owner = {}
if (OwnerOptions.selectedAccountType === this.$t('label.account')) { if (OwnerOptions.selectedAccountType === 'Account') {
if (!OwnerOptions.selectedAccount) { if (!OwnerOptions.selectedAccount) {
return return
} }
this.owner.account = OwnerOptions.selectedAccount this.owner.account = OwnerOptions.selectedAccount
this.owner.domainid = OwnerOptions.selectedDomain this.owner.domainid = OwnerOptions.selectedDomain
} else if (OwnerOptions.selectedAccountType === this.$t('label.project')) { } else if (OwnerOptions.selectedAccountType === 'Project') {
if (!OwnerOptions.selectedProject) { if (!OwnerOptions.selectedProject) {
return return
} }