Skip to content

Commit a4d9c18

Browse files
authored
Merge branch 'apache:main' into main
2 parents 44abe66 + 8a16729 commit a4d9c18

File tree

22 files changed

+1359
-142
lines changed

22 files changed

+1359
-142
lines changed

api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,10 @@ public Type getType() {
146146
return type;
147147
}
148148

149+
public void setType(Type type) {
150+
this.type = type;
151+
}
152+
149153
public BootloaderType getBootloader() {
150154
return bootloader;
151155
}

core/src/main/java/com/cloud/agent/api/ScaleVmCommand.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,6 @@ public ScaleVmCommand(String vmName, int cpus, Integer minSpeed, Integer maxSpee
5252
this.minRam = minRam;
5353
this.maxRam = maxRam;
5454
this.vm = new VirtualMachineTO(1L, vmName, null, cpus, minSpeed, maxSpeed, minRam, maxRam, null, null, false, limitCpuUse, null);
55-
/*vm.setName(vmName);
56-
vm.setCpus(cpus);
57-
vm.setRam(minRam, maxRam);*/
5855
}
5956

6057
public void setCpus(int cpus) {

core/src/main/java/com/cloud/resource/CommandWrapper.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@
2121

2222
import com.cloud.agent.api.Answer;
2323
import com.cloud.agent.api.Command;
24+
import org.apache.log4j.Logger;
2425

2526
public abstract class CommandWrapper<T extends Command, A extends Answer, R extends ServerResource> {
27+
protected Logger logger = Logger.getLogger(getClass());
2628

2729
/**
2830
* @param T is the command to be used.

engine/api/src/main/java/com/cloud/vm/VirtualMachineManager.java

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -76,22 +76,6 @@ public interface VirtualMachineManager extends Manager {
7676
ConfigKey<Boolean> AllowExposeHypervisorHostname = new ConfigKey<Boolean>("Advanced", Boolean.class, "global.allow.expose.host.hostname",
7777
"false", "If set to true, it allows the hypervisor host name on which the VM is spawned on to be exposed to the VM", true, ConfigKey.Scope.Global);
7878

79-
static final ConfigKey<Integer> VmServiceOfferingMaxCPUCores = new ConfigKey<Integer>("Advanced",
80-
Integer.class,
81-
"vm.serviceoffering.cpu.cores.max",
82-
"0",
83-
"Maximum CPU cores for vm service offering. If 0 - no limitation",
84-
true
85-
);
86-
87-
static final ConfigKey<Integer> VmServiceOfferingMaxRAMSize = new ConfigKey<Integer>("Advanced",
88-
Integer.class,
89-
"vm.serviceoffering.ram.size.max",
90-
"0",
91-
"Maximum RAM size in MB for vm service offering. If 0 - no limitation",
92-
true
93-
);
94-
9579
interface Topics {
9680
String VM_POWER_STATE = "vm.powerstate";
9781
}

engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4665,6 +4665,8 @@ public VMInstanceVO reConfigureVm(final String vmUuid, final ServiceOffering old
46654665
throw (ConcurrentOperationException)jobResult;
46664666
} else if (jobResult instanceof InsufficientServerCapacityException) {
46674667
throw (InsufficientServerCapacityException)jobResult;
4668+
} else if (jobResult instanceof RuntimeException) {
4669+
throw (RuntimeException)jobResult;
46684670
} else if (jobResult instanceof Throwable) {
46694671
s_logger.error("Unhandled exception", (Throwable)jobResult);
46704672
throw new RuntimeException("Unhandled exception", (Throwable)jobResult);
@@ -4677,8 +4679,7 @@ public VMInstanceVO reConfigureVm(final String vmUuid, final ServiceOffering old
46774679

46784680
private VMInstanceVO orchestrateReConfigureVm(String vmUuid, ServiceOffering oldServiceOffering, ServiceOffering newServiceOffering,
46794681
boolean reconfiguringOnExistingHost) throws ResourceUnavailableException, ConcurrentOperationException {
4680-
VMInstanceVO vm = _vmDao.findByUuid(vmUuid);
4681-
upgradeVmDb(vm.getId(), newServiceOffering, oldServiceOffering);
4682+
final VMInstanceVO vm = _vmDao.findByUuid(vmUuid);
46824683

46834684
HostVO hostVo = _hostDao.findById(vm.getHostId());
46844685

@@ -4695,6 +4696,10 @@ private VMInstanceVO orchestrateReConfigureVm(String vmUuid, ServiceOffering old
46954696
new ScaleVmCommand(vm.getInstanceName(), newServiceOffering.getCpu(), minSpeed,
46964697
newServiceOffering.getSpeed(), minMemory * 1024L * 1024L, newServiceOffering.getRamSize() * 1024L * 1024L, newServiceOffering.getLimitCpuUse());
46974698

4699+
scaleVmCommand.getVirtualMachine().setId(vm.getId());
4700+
scaleVmCommand.getVirtualMachine().setUuid(vm.getUuid());
4701+
scaleVmCommand.getVirtualMachine().setType(vm.getType());
4702+
46984703
Long dstHostId = vm.getHostId();
46994704

47004705
if (vm.getHypervisorType().equals(HypervisorType.VMware)) {
@@ -4710,36 +4715,31 @@ private VMInstanceVO orchestrateReConfigureVm(String vmUuid, ServiceOffering old
47104715
work.setResourceId(vm.getHostId());
47114716
_workDao.persist(work);
47124717

4713-
boolean success = false;
4714-
47154718
try {
4719+
Answer reconfigureAnswer = _agentMgr.send(vm.getHostId(), scaleVmCommand);
4720+
4721+
if (reconfigureAnswer == null || !reconfigureAnswer.getResult()) {
4722+
s_logger.error("Unable to scale vm due to " + (reconfigureAnswer == null ? "" : reconfigureAnswer.getDetails()));
4723+
throw new CloudRuntimeException("Unable to scale vm due to " + (reconfigureAnswer == null ? "" : reconfigureAnswer.getDetails()));
4724+
}
4725+
4726+
if (vm.getType().equals(VirtualMachine.Type.User)) {
4727+
_userVmMgr.generateUsageEvent(vm, vm.isDisplayVm(), EventTypes.EVENT_VM_DYNAMIC_SCALE);
4728+
}
4729+
4730+
upgradeVmDb(vm.getId(), newServiceOffering, oldServiceOffering);
4731+
47164732
if (reconfiguringOnExistingHost) {
47174733
vm.setServiceOfferingId(oldServiceOffering.getId());
47184734
_capacityMgr.releaseVmCapacity(vm, false, false, vm.getHostId()); //release the old capacity
47194735
vm.setServiceOfferingId(newServiceOffering.getId());
47204736
_capacityMgr.allocateVmCapacity(vm, false); // lock the new capacity
47214737
}
47224738

4723-
Answer scaleVmAnswer = _agentMgr.send(vm.getHostId(), scaleVmCommand);
4724-
if (scaleVmAnswer == null || !scaleVmAnswer.getResult()) {
4725-
String msg = String.format("Unable to scale %s due to [%s].", vm.toString(), (scaleVmAnswer == null ? "" : scaleVmAnswer.getDetails()));
4726-
s_logger.error(msg);
4727-
throw new CloudRuntimeException(msg);
4728-
}
4729-
if (vm.getType().equals(VirtualMachine.Type.User)) {
4730-
_userVmMgr.generateUsageEvent(vm, vm.isDisplayVm(), EventTypes.EVENT_VM_DYNAMIC_SCALE);
4731-
}
4732-
success = true;
4733-
} catch (OperationTimedoutException e) {
4734-
throw new AgentUnavailableException(String.format("Unable to scale %s due to [%s].", vm.toString(), e.getMessage()), dstHostId, e);
4739+
} catch (final OperationTimedoutException e) {
4740+
throw new AgentUnavailableException("Operation timed out on reconfiguring " + vm, dstHostId);
47354741
} catch (final AgentUnavailableException e) {
47364742
throw e;
4737-
} finally {
4738-
if (!success) {
4739-
_capacityMgr.releaseVmCapacity(vm, false, false, vm.getHostId()); // release the new capacity
4740-
upgradeVmDb(vm.getId(), oldServiceOffering, newServiceOffering); // rollback
4741-
_capacityMgr.allocateVmCapacity(vm, false); // allocate the old capacity
4742-
}
47434743
}
47444744

47454745
return vm;
@@ -4783,8 +4783,7 @@ public ConfigKey<?>[] getConfigKeys() {
47834783
return new ConfigKey<?>[] { ClusterDeltaSyncInterval, StartRetry, VmDestroyForcestop, VmOpCancelInterval, VmOpCleanupInterval, VmOpCleanupWait,
47844784
VmOpLockStateRetry, VmOpWaitInterval, ExecuteInSequence, VmJobCheckInterval, VmJobTimeout, VmJobStateReportInterval,
47854785
VmConfigDriveLabel, VmConfigDriveOnPrimaryPool, VmConfigDriveForceHostCacheUse, VmConfigDriveUseHostCacheOnUnsupportedPool,
4786-
HaVmRestartHostUp, ResoureCountRunningVMsonly, AllowExposeHypervisorHostname, AllowExposeHypervisorHostnameAccountLevel,
4787-
VmServiceOfferingMaxCPUCores, VmServiceOfferingMaxRAMSize };
4786+
HaVmRestartHostUp, ResoureCountRunningVMsonly, AllowExposeHypervisorHostname, AllowExposeHypervisorHostnameAccountLevel };
47884787
}
47894788

47904789
public List<StoragePoolAllocator> getStoragePoolAllocators() {

engine/schema/src/main/java/com/cloud/host/HostVO.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,7 @@ public boolean equals(Object obj) {
680680

681681
@Override
682682
public String toString() {
683-
return String.format("Host [{id: \"%s\", name: \"%s\", uuid: \"%s\", type=\"%s\"}]", id, name, uuid, type);
683+
return String.format("Host {\"id\": \"%s\", \"name\": \"%s\", \"uuid\": \"%s\", \"type\"=\"%s\"}", id, name, uuid, type);
684684
}
685685

686686
public void setHypervisorType(HypervisorType hypervisorType) {

engine/schema/src/main/java/com/cloud/service/ServiceOfferingVO.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,10 @@ public boolean isCustomCpuSpeedSupported() {
298298
}
299299

300300
@Override
301+
public String toString() {
302+
return String.format("Service offering {\"id\": %s, \"name\": \"%s\", \"uuid\": \"%s\"}", getId(), getName(), getUuid());
303+
}
304+
301305
public boolean isDynamicScalingEnabled() {
302306
return dynamicScalingEnabled;
303307
}

engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategy.java

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,6 @@
102102
import com.cloud.storage.DataStoreRole;
103103
import com.cloud.storage.DiskOfferingVO;
104104
import com.cloud.storage.MigrationOptions;
105-
import com.cloud.storage.ScopeType;
106105
import com.cloud.storage.Snapshot;
107106
import com.cloud.storage.SnapshotVO;
108107
import com.cloud.storage.Storage;
@@ -2259,19 +2258,26 @@ protected void verifyLiveMigrationForKVM(Map<VolumeInfo, DataStore> volumeDataSt
22592258
throw new CloudRuntimeException("Destination storage pools must be either all managed or all not managed");
22602259
}
22612260

2262-
if (!destStoragePoolVO.isManaged() && destStoragePoolVO.getPoolType() == StoragePoolType.NetworkFilesystem) {
2263-
if (destStoragePoolVO.getScope() != ScopeType.CLUSTER) {
2264-
throw new CloudRuntimeException("KVM live storage migrations currently support cluster-wide " +
2265-
"not managed NFS destination storage");
2266-
}
2267-
if (!sourcePools.containsKey(srcStoragePoolVO.getUuid())) {
2268-
sourcePools.put(srcStoragePoolVO.getUuid(), srcStoragePoolVO.getPoolType());
2269-
}
2270-
}
2261+
addSourcePoolToPoolsMap(sourcePools, srcStoragePoolVO, destStoragePoolVO);
22712262
}
22722263
verifyDestinationStorage(sourcePools, destHost);
22732264
}
22742265

2266+
/**
2267+
* Adds source storage pool to the migration map if the destination pool is not managed and it is NFS.
2268+
*/
2269+
protected void addSourcePoolToPoolsMap(Map<String, Storage.StoragePoolType> sourcePools, StoragePoolVO srcStoragePoolVO, StoragePoolVO destStoragePoolVO) {
2270+
if (destStoragePoolVO.isManaged() || !StoragePoolType.NetworkFilesystem.equals(destStoragePoolVO.getPoolType())) {
2271+
LOGGER.trace(String.format("Skipping adding source pool [%s] to map due to destination pool [%s] is managed or not NFS.", srcStoragePoolVO, destStoragePoolVO));
2272+
return;
2273+
}
2274+
2275+
String sourceStoragePoolUuid = srcStoragePoolVO.getUuid();
2276+
if (!sourcePools.containsKey(sourceStoragePoolUuid)) {
2277+
sourcePools.put(sourceStoragePoolUuid, srcStoragePoolVO.getPoolType());
2278+
}
2279+
}
2280+
22752281
/**
22762282
* Perform storage validation on destination host for KVM live storage migrations.
22772283
* Validate that volume source storage pools are mounted on the destination host prior the migration

engine/storage/datamotion/src/test/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategyTest.java

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import static org.mockito.Mockito.doReturn;
2424
import static org.mockito.Mockito.lenient;
2525
import static org.mockito.Mockito.mock;
26+
import static org.mockito.Mockito.never;
2627
import static org.mockito.MockitoAnnotations.initMocks;
2728

2829
import java.util.HashMap;
@@ -47,17 +48,22 @@
4748
import org.mockito.Mockito;
4849
import org.mockito.Spy;
4950
import org.mockito.runners.MockitoJUnitRunner;
51+
import org.mockito.verification.VerificationMode;
5052

5153
import com.cloud.agent.api.MigrateCommand;
5254
import com.cloud.host.HostVO;
5355
import com.cloud.storage.DataStoreRole;
5456
import com.cloud.storage.ImageStore;
57+
import com.cloud.storage.ScopeType;
5558
import com.cloud.storage.Storage;
5659
import com.cloud.storage.Storage.StoragePoolType;
5760
import com.cloud.storage.Volume;
5861
import com.cloud.storage.VolumeVO;
5962
import java.util.AbstractMap;
63+
import java.util.Arrays;
6064
import java.util.HashSet;
65+
import java.util.LinkedList;
66+
import java.util.List;
6167
import java.util.Set;
6268

6369
@RunWith(MockitoJUnitRunner.class)
@@ -78,6 +84,14 @@ public class StorageSystemDataMotionStrategyTest {
7884
@Mock
7985
private PrimaryDataStoreDao primaryDataStoreDao;
8086

87+
@Mock
88+
StoragePoolVO sourceStoragePoolVoMock, destinationStoragePoolVoMock;
89+
90+
@Mock
91+
Map<String, Storage.StoragePoolType> mapStringStoragePoolTypeMock;
92+
93+
List<ScopeType> scopeTypes = Arrays.asList(ScopeType.CLUSTER, ScopeType.ZONE);
94+
8195
@Before
8296
public void setUp() throws Exception {
8397
sourceStore = mock(PrimaryDataStoreImpl.class);
@@ -345,4 +359,72 @@ public void validateIsStoragePoolTypeInListReturnsFalse() {
345359

346360
assertFalse(strategy.isStoragePoolTypeInList(StoragePoolType.SharedMountPoint, listTypes));
347361
}
362+
363+
@Test
364+
public void validateAddSourcePoolToPoolsMapDestinationPoolIsManaged() {
365+
Mockito.doReturn(true).when(destinationStoragePoolVoMock).isManaged();
366+
strategy.addSourcePoolToPoolsMap(mapStringStoragePoolTypeMock, sourceStoragePoolVoMock, destinationStoragePoolVoMock);
367+
368+
Mockito.verify(destinationStoragePoolVoMock).isManaged();
369+
Mockito.verifyNoMoreInteractions(mapStringStoragePoolTypeMock, sourceStoragePoolVoMock, destinationStoragePoolVoMock);
370+
}
371+
372+
@Test
373+
public void validateAddSourcePoolToPoolsMapDestinationPoolIsNotNFS() {
374+
List<StoragePoolType> storagePoolTypes = new LinkedList<>(Arrays.asList(StoragePoolType.values()));
375+
storagePoolTypes.remove(StoragePoolType.NetworkFilesystem);
376+
377+
Mockito.doReturn(false).when(destinationStoragePoolVoMock).isManaged();
378+
storagePoolTypes.forEach(poolType -> {
379+
Mockito.doReturn(poolType).when(destinationStoragePoolVoMock).getPoolType();
380+
strategy.addSourcePoolToPoolsMap(mapStringStoragePoolTypeMock, sourceStoragePoolVoMock, destinationStoragePoolVoMock);
381+
});
382+
383+
VerificationMode times = Mockito.times(storagePoolTypes.size());
384+
Mockito.verify(destinationStoragePoolVoMock, times).isManaged();
385+
Mockito.verify(destinationStoragePoolVoMock, times).getPoolType();
386+
Mockito.verifyNoMoreInteractions(mapStringStoragePoolTypeMock, sourceStoragePoolVoMock, destinationStoragePoolVoMock);
387+
}
388+
389+
@Test
390+
public void validateAddSourcePoolToPoolsMapMapContainsKey() {
391+
Mockito.doReturn(false).when(destinationStoragePoolVoMock).isManaged();
392+
Mockito.doReturn(StoragePoolType.NetworkFilesystem).when(destinationStoragePoolVoMock).getPoolType();
393+
Mockito.doReturn("").when(sourceStoragePoolVoMock).getUuid();
394+
Mockito.doReturn(true).when(mapStringStoragePoolTypeMock).containsKey(Mockito.anyString());
395+
strategy.addSourcePoolToPoolsMap(mapStringStoragePoolTypeMock, sourceStoragePoolVoMock, destinationStoragePoolVoMock);
396+
397+
Mockito.verify(destinationStoragePoolVoMock, never()).getScope();
398+
Mockito.verify(destinationStoragePoolVoMock).isManaged();
399+
Mockito.verify(destinationStoragePoolVoMock).getPoolType();
400+
Mockito.verify(sourceStoragePoolVoMock).getUuid();
401+
Mockito.verify(mapStringStoragePoolTypeMock).containsKey(Mockito.anyString());
402+
Mockito.verifyNoMoreInteractions(mapStringStoragePoolTypeMock, sourceStoragePoolVoMock, destinationStoragePoolVoMock);
403+
}
404+
405+
@Test
406+
public void validateAddSourcePoolToPoolsMapMapDoesNotContainsKey() {
407+
List<StoragePoolType> storagePoolTypes = new LinkedList<>(Arrays.asList(StoragePoolType.values()));
408+
409+
Mockito.doReturn(false).when(destinationStoragePoolVoMock).isManaged();
410+
Mockito.doReturn(StoragePoolType.NetworkFilesystem).when(destinationStoragePoolVoMock).getPoolType();
411+
Mockito.doReturn("").when(sourceStoragePoolVoMock).getUuid();
412+
Mockito.doReturn(false).when(mapStringStoragePoolTypeMock).containsKey(Mockito.anyString());
413+
Mockito.doReturn(null).when(mapStringStoragePoolTypeMock).put(Mockito.anyString(), Mockito.any());
414+
415+
storagePoolTypes.forEach(poolType -> {
416+
Mockito.doReturn(poolType).when(sourceStoragePoolVoMock).getPoolType();
417+
strategy.addSourcePoolToPoolsMap(mapStringStoragePoolTypeMock, sourceStoragePoolVoMock, destinationStoragePoolVoMock);
418+
});
419+
420+
VerificationMode times = Mockito.times(storagePoolTypes.size());
421+
Mockito.verify(destinationStoragePoolVoMock, never()).getScope();
422+
Mockito.verify(destinationStoragePoolVoMock, times).isManaged();
423+
Mockito.verify(destinationStoragePoolVoMock, times).getPoolType();
424+
Mockito.verify(sourceStoragePoolVoMock, times).getUuid();
425+
Mockito.verify(mapStringStoragePoolTypeMock, times).containsKey(Mockito.anyString());
426+
Mockito.verify(sourceStoragePoolVoMock, times).getPoolType();
427+
Mockito.verify(mapStringStoragePoolTypeMock, times).put(Mockito.anyString(), Mockito.any());
428+
Mockito.verifyNoMoreInteractions(mapStringStoragePoolTypeMock, sourceStoragePoolVoMock, destinationStoragePoolVoMock);
429+
}
348430
}

0 commit comments

Comments
 (0)