Skip to content

Commit 46cdc27

Browse files
committed
Merge branch '4.22' into 422-vmware-to-kvm-guestos
2 parents 1db51ba + e93ae1a commit 46cdc27

File tree

8 files changed

+61
-18
lines changed

8 files changed

+61
-18
lines changed

api/src/main/java/org/apache/cloudstack/storage/volume/VolumeImportUnmanageService.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,29 @@
2525
import org.apache.cloudstack.api.response.ListResponse;
2626
import org.apache.cloudstack.api.response.VolumeForImportResponse;
2727
import org.apache.cloudstack.api.response.VolumeResponse;
28+
import org.apache.cloudstack.framework.config.ConfigKey;
29+
import org.apache.cloudstack.framework.config.Configurable;
2830

2931
import java.util.Arrays;
3032
import java.util.List;
3133

32-
public interface VolumeImportUnmanageService extends PluggableService {
34+
public interface VolumeImportUnmanageService extends PluggableService, Configurable {
3335

3436
List<Hypervisor.HypervisorType> SUPPORTED_HYPERVISORS =
3537
Arrays.asList(Hypervisor.HypervisorType.KVM, Hypervisor.HypervisorType.VMware);
3638

3739
List<Storage.StoragePoolType> SUPPORTED_STORAGE_POOL_TYPES_FOR_KVM = Arrays.asList(Storage.StoragePoolType.NetworkFilesystem,
3840
Storage.StoragePoolType.Filesystem, Storage.StoragePoolType.RBD);
3941

42+
ConfigKey<Boolean> AllowImportVolumeWithBackingFile = new ConfigKey<>(Boolean.class,
43+
"allow.import.volume.with.backing.file",
44+
"Advanced",
45+
"false",
46+
"If enabled, allows QCOW2 volumes with backing files to be imported or unmanaged",
47+
true,
48+
ConfigKey.Scope.Global,
49+
null);
50+
4051
ListResponse<VolumeForImportResponse> listVolumesForImport(ListVolumesForImportCmd cmd);
4152

4253
VolumeResponse importVolume(ImportVolumeCmd cmd);

engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreDaoImpl.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase<SnapshotDataStoreVO
6767
private SearchBuilder<SnapshotDataStoreVO> searchFilteringStoreIdEqStoreRoleEqStateNeqRefCntNeq;
6868
protected SearchBuilder<SnapshotDataStoreVO> searchFilteringStoreIdEqStateEqStoreRoleEqIdEqUpdateCountEqSnapshotIdEqVolumeIdEq;
6969
private SearchBuilder<SnapshotDataStoreVO> stateSearch;
70-
private SearchBuilder<SnapshotDataStoreVO> idStateNeqSearch;
70+
private SearchBuilder<SnapshotDataStoreVO> idStateNinSearch;
7171
protected SearchBuilder<SnapshotVO> snapshotVOSearch;
7272
private SearchBuilder<SnapshotDataStoreVO> snapshotCreatedSearch;
7373
private SearchBuilder<SnapshotDataStoreVO> dataStoreAndInstallPathSearch;
@@ -146,10 +146,10 @@ public boolean configure(String name, Map<String, Object> params) throws Configu
146146
stateSearch.done();
147147

148148

149-
idStateNeqSearch = createSearchBuilder();
150-
idStateNeqSearch.and(SNAPSHOT_ID, idStateNeqSearch.entity().getSnapshotId(), SearchCriteria.Op.EQ);
151-
idStateNeqSearch.and(STATE, idStateNeqSearch.entity().getState(), SearchCriteria.Op.NEQ);
152-
idStateNeqSearch.done();
149+
idStateNinSearch = createSearchBuilder();
150+
idStateNinSearch.and(SNAPSHOT_ID, idStateNinSearch.entity().getSnapshotId(), SearchCriteria.Op.EQ);
151+
idStateNinSearch.and(STATE, idStateNinSearch.entity().getState(), SearchCriteria.Op.NOTIN);
152+
idStateNinSearch.done();
153153

154154
snapshotVOSearch = snapshotDao.createSearchBuilder();
155155
snapshotVOSearch.and(VOLUME_ID, snapshotVOSearch.entity().getVolumeId(), SearchCriteria.Op.EQ);
@@ -480,15 +480,15 @@ public List<SnapshotDataStoreVO> findBySnapshotId(long snapshotId) {
480480

481481
@Override
482482
public List<SnapshotDataStoreVO> findBySnapshotIdWithNonDestroyedState(long snapshotId) {
483-
SearchCriteria<SnapshotDataStoreVO> sc = idStateNeqSearch.create();
483+
SearchCriteria<SnapshotDataStoreVO> sc = idStateNinSearch.create();
484484
sc.setParameters(SNAPSHOT_ID, snapshotId);
485485
sc.setParameters(STATE, State.Destroyed.name());
486486
return listBy(sc);
487487
}
488488

489489
@Override
490490
public List<SnapshotDataStoreVO> findBySnapshotIdAndNotInDestroyedHiddenState(long snapshotId) {
491-
SearchCriteria<SnapshotDataStoreVO> sc = idStateNeqSearch.create();
491+
SearchCriteria<SnapshotDataStoreVO> sc = idStateNinSearch.create();
492492
sc.setParameters(SNAPSHOT_ID, snapshotId);
493493
sc.setParameters(STATE, State.Destroyed.name(), State.Hidden.name());
494494
return listBy(sc);

server/src/main/java/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1738,6 +1738,8 @@ public LoadBalancer createPublicLoadBalancerRule(String xId, String name, String
17381738
throw new NetworkRuleConflictException("Can't do load balance on IP address: " + ipVO.getAddress());
17391739
}
17401740

1741+
verifyLoadBalancerRuleNetwork(name, network, ipVO);
1742+
17411743
String cidrString = generateCidrString(cidrList);
17421744

17431745
boolean performedIpAssoc = false;
@@ -1790,7 +1792,17 @@ public LoadBalancer createPublicLoadBalancerRule(String xId, String name, String
17901792

17911793
return result;
17921794
}
1793-
/**
1795+
1796+
protected void verifyLoadBalancerRuleNetwork(String lbName, Network network, IPAddressVO ipVO) {
1797+
if (ipVO.getAssociatedWithNetworkId() != null && network.getId() != ipVO.getAssociatedWithNetworkId()) {
1798+
String msg = String.format("Cannot create Load Balancer rule %s as the IP address %s is not associated " +
1799+
"with the network %s (ID=%s)", lbName, ipVO.getAddress(), network.getName(), network.getUuid());
1800+
logger.error(msg);
1801+
throw new InvalidParameterValueException(msg);
1802+
}
1803+
}
1804+
1805+
/**
17941806
* Transforms the cidrList from a List of Strings to a String which contains all the CIDRs from cidrList separated by whitespaces. This is used to facilitate both the persistence
17951807
* in the DB and also later when building the configuration String in the getRulesForPool method of the HAProxyConfigurator class.
17961808
*/

server/src/main/java/org/apache/cloudstack/storage/volume/VolumeImportUnmanageManagerImpl.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
import org.apache.cloudstack.api.response.VolumeResponse;
6969
import org.apache.cloudstack.context.CallContext;
7070
import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
71+
import org.apache.cloudstack.framework.config.ConfigKey;
7172
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
7273
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
7374
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
@@ -394,7 +395,7 @@ protected void checkIfVolumeHasBackingFile(VolumeOnStorageTO volume) {
394395
Map<VolumeOnStorageTO.Detail, String> volumeDetails = volume.getDetails();
395396
if (volumeDetails != null && volumeDetails.containsKey(VolumeOnStorageTO.Detail.BACKING_FILE)) {
396397
String backingFile = volumeDetails.get(VolumeOnStorageTO.Detail.BACKING_FILE);
397-
if (StringUtils.isNotBlank(backingFile)) {
398+
if (StringUtils.isNotBlank(backingFile) && !AllowImportVolumeWithBackingFile.value()) {
398399
logFailureAndThrowException("Volume with backing file cannot be imported or unmanaged.");
399400
}
400401
}
@@ -513,4 +514,16 @@ private void unmanageVolumeFromDatabase(VolumeVO volume) {
513514
volume.setRemoved(new Date());
514515
volumeDao.update(volume.getId(), volume);
515516
}
517+
518+
@Override
519+
public String getConfigComponentName() {
520+
return VolumeImportUnmanageManagerImpl.class.getSimpleName();
521+
}
522+
523+
@Override
524+
public ConfigKey<?>[] getConfigKeys() {
525+
return new ConfigKey<?>[]{
526+
AllowImportVolumeWithBackingFile
527+
};
528+
}
516529
}

server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@
195195

196196
import static org.apache.cloudstack.api.ApiConstants.MAX_IOPS;
197197
import static org.apache.cloudstack.api.ApiConstants.MIN_IOPS;
198+
import static org.apache.cloudstack.storage.volume.VolumeImportUnmanageService.AllowImportVolumeWithBackingFile;
198199
import static org.apache.cloudstack.vm.ImportVmTask.Step.CloningInstance;
199200
import static org.apache.cloudstack.vm.ImportVmTask.Step.Completed;
200201
import static org.apache.cloudstack.vm.ImportVmTask.Step.ConvertingInstance;
@@ -2924,7 +2925,7 @@ private void checkVolume(Map<VolumeOnStorageTO.Detail, String> volumeDetails) {
29242925
}
29252926
if (volumeDetails.containsKey(VolumeOnStorageTO.Detail.BACKING_FILE)) {
29262927
String backingFile = volumeDetails.get(VolumeOnStorageTO.Detail.BACKING_FILE);
2927-
if (StringUtils.isNotBlank(backingFile)) {
2928+
if (StringUtils.isNotBlank(backingFile) && !AllowImportVolumeWithBackingFile.value()) {
29282929
logFailureAndThrowException("Volume with backing file cannot be imported or unmanaged.");
29292930
}
29302931
}

test/integration/smoke/test_secondary_storage.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,11 @@ def test_01_sys_vm_start(self):
136136
'Up',
137137
"Check state of primary storage pools is Up or not"
138138
)
139-
for _ in range(2):
139+
# Poll until all SSVMs are Running, or timeout after 3 minutes
140+
timeout = 180
141+
interval = 15
142+
list_ssvm_response = []
143+
while timeout > 0:
140144
list_ssvm_response = list_ssvms(
141145
self.apiclient,
142146
systemvmtype='secondarystoragevm',
@@ -154,10 +158,12 @@ def test_01_sys_vm_start(self):
154158
"Check list System VMs response"
155159
)
156160

157-
for ssvm in list_ssvm_response:
158-
if ssvm.state != 'Running':
159-
time.sleep(30)
160-
continue
161+
if all(ssvm.state == 'Running' for ssvm in list_ssvm_response):
162+
break
163+
164+
time.sleep(interval)
165+
timeout -= interval
166+
161167
for ssvm in list_ssvm_response:
162168
self.assertEqual(
163169
ssvm.state,

vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/BaseMO.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ private UnmanagedInstanceTO createUnmanagedInstanceTOFromThinListingDynamicPrope
236236
} else if (objProp.getName().equals("config.bootOptions")) {
237237
VirtualMachineBootOptions bootOptions = (VirtualMachineBootOptions) objProp.getVal();
238238
String bootMode = "LEGACY";
239-
if (bootOptions != null && bootOptions.isEfiSecureBootEnabled()) {
239+
if (bootOptions != null && Boolean.TRUE.equals(bootOptions.isEfiSecureBootEnabled())) {
240240
bootMode = "SECURE";
241241
}
242242
vm.setBootMode(bootMode);

vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareHelper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -820,7 +820,7 @@ public static UnmanagedInstanceTO getUnmanagedInstance(VmwareHypervisorHost hype
820820
instance.setBootType(firmware.equalsIgnoreCase("efi") ? "UEFI" : "BIOS");
821821
VirtualMachineBootOptions bootOptions = configInfo.getBootOptions();
822822
String bootMode = "LEGACY";
823-
if (bootOptions != null && bootOptions.isEfiSecureBootEnabled()) {
823+
if (bootOptions != null && Boolean.TRUE.equals(bootOptions.isEfiSecureBootEnabled())) {
824824
bootMode = "SECURE";
825825
}
826826
instance.setBootMode(bootMode);

0 commit comments

Comments
 (0)