Skip to content

Commit 5812290

Browse files
committed
Merge remote-tracking branch 'apache/4.22'
2 parents 27722a5 + a8c8c18 commit 5812290

16 files changed

Lines changed: 328 additions & 105 deletions

File tree

‎.editorconfig‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
root = true
18+
19+
[*]
20+
charset = utf-8
21+
end_of_line = lf
22+
# indent_size = 4
23+
indent_style = space
24+
insert_final_newline = true
25+
# max_line_length = 120
26+
# tab_width = 4

‎api/src/main/java/com/cloud/resource/ResourceService.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ public interface ResourceService {
9191

9292
DataCenter getZone(Long zoneId);
9393

94-
List<HypervisorType> getSupportedHypervisorTypes(long zoneId, boolean forVirtualRouter, Long podId);
94+
List<HypervisorType> getSupportedHypervisorTypes(long zoneId, boolean forSystemVm, Long podId);
9595

9696
boolean releaseHostReservation(Long hostId);
9797

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,15 @@ private boolean canBypassSecondaryStorage(DataObject srcData, DataObject destDat
556556
return true;
557557
}
558558

559+
if (Hypervisor.HypervisorType.XenServer.equals(((VolumeInfo) srcData).getHypervisorType())) {
560+
return false;
561+
}
562+
559563
if (destData instanceof VolumeInfo) {
564+
if (Hypervisor.HypervisorType.XenServer.equals(((VolumeInfo) destData).getHypervisorType())) {
565+
return false;
566+
}
567+
560568
Scope srcDataStoreScope = srcData.getDataStore().getScope();
561569
Scope destDataStoreScope = destData.getDataStore().getScope();
562570
logger.info("srcDataStoreScope: {}, srcData pool type: {}; destDataStoreScope: {}, destData pool type: {}",

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ public void testCanBypassSecondaryStorageForDirectDownload() throws NoSuchMethod
143143
@Test
144144
public void testCanBypassSecondaryStorageForUnsupportedDataObject() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
145145
VolumeObject srcVolumeInfo = Mockito.spy(new VolumeObject());
146+
Mockito.doReturn(HypervisorType.KVM).when(srcVolumeInfo).getHypervisorType();
146147

147148
TemplateObject destTemplateInfo = Mockito.spy(new TemplateObject());
148149

@@ -156,12 +157,14 @@ public void testCanBypassSecondaryStorageForUnsupportedDataObject() throws NoSuc
156157
@Test
157158
public void testCanBypassSecondaryStorageForUnsupportedSrcPoolType() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
158159
VolumeObject srcVolumeInfo = Mockito.spy(new VolumeObject());
160+
Mockito.doReturn(HypervisorType.KVM).when(srcVolumeInfo).getHypervisorType();
159161
DataStore srcDataStore = Mockito.mock(DataStore.class);
160162
Mockito.doReturn(new ZoneScope(1L)).when(srcDataStore).getScope();
161163
Mockito.doReturn(srcDataStore).when(srcVolumeInfo).getDataStore();
162164
Mockito.doReturn(Storage.StoragePoolType.PowerFlex).when(srcVolumeInfo).getStoragePoolType();
163165

164166
VolumeObject destVolumeInfo = Mockito.spy(new VolumeObject());
167+
Mockito.doReturn(HypervisorType.KVM).when(destVolumeInfo).getHypervisorType();
165168
DataStore destDataStore = Mockito.mock(DataStore.class);
166169
Mockito.doReturn(new ZoneScope(1L)).when(destDataStore).getScope();
167170
Mockito.doReturn(destDataStore).when(destVolumeInfo).getDataStore();
@@ -177,12 +180,14 @@ public void testCanBypassSecondaryStorageForUnsupportedSrcPoolType() throws NoSu
177180
@Test
178181
public void testCanBypassSecondaryStorageForUnsupportedDestPoolType() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
179182
VolumeObject srcVolumeInfo = Mockito.spy(new VolumeObject());
183+
Mockito.doReturn(HypervisorType.KVM).when(srcVolumeInfo).getHypervisorType();
180184
DataStore srcDataStore = Mockito.mock(DataStore.class);
181185
Mockito.doReturn(new ZoneScope(1L)).when(srcDataStore).getScope();
182186
Mockito.doReturn(srcDataStore).when(srcVolumeInfo).getDataStore();
183187
Mockito.doReturn(Storage.StoragePoolType.NetworkFilesystem).when(srcVolumeInfo).getStoragePoolType();
184188

185189
VolumeObject destVolumeInfo = Mockito.spy(new VolumeObject());
190+
Mockito.doReturn(HypervisorType.KVM).when(destVolumeInfo).getHypervisorType();
186191
DataStore destDataStore = Mockito.mock(DataStore.class);
187192
Mockito.doReturn(new ZoneScope(1L)).when(destDataStore).getScope();
188193
Mockito.doReturn(destDataStore).when(destVolumeInfo).getDataStore();
@@ -198,12 +203,14 @@ public void testCanBypassSecondaryStorageForUnsupportedDestPoolType() throws NoS
198203
@Test
199204
public void testCanBypassSecondaryStorageWithZoneWideNFSPoolsInSameZone() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
200205
VolumeObject srcVolumeInfo = Mockito.spy(new VolumeObject());
206+
Mockito.doReturn(HypervisorType.KVM).when(srcVolumeInfo).getHypervisorType();
201207
DataStore srcDataStore = Mockito.mock(DataStore.class);
202208
Mockito.doReturn(new ZoneScope(1L)).when(srcDataStore).getScope();
203209
Mockito.doReturn(srcDataStore).when(srcVolumeInfo).getDataStore();
204210
Mockito.doReturn(Storage.StoragePoolType.NetworkFilesystem).when(srcVolumeInfo).getStoragePoolType();
205211

206212
VolumeObject destVolumeInfo = Mockito.spy(new VolumeObject());
213+
Mockito.doReturn(HypervisorType.KVM).when(destVolumeInfo).getHypervisorType();
207214
DataStore destDataStore = Mockito.mock(DataStore.class);
208215
Mockito.doReturn(new ZoneScope(1L)).when(destDataStore).getScope();
209216
Mockito.doReturn(destDataStore).when(destVolumeInfo).getDataStore();
@@ -219,12 +226,14 @@ public void testCanBypassSecondaryStorageWithZoneWideNFSPoolsInSameZone() throws
219226
@Test
220227
public void testCanBypassSecondaryStorageWithClusterWideNFSPoolsInSameCluster() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
221228
VolumeObject srcVolumeInfo = Mockito.spy(new VolumeObject());
229+
Mockito.doReturn(HypervisorType.KVM).when(srcVolumeInfo).getHypervisorType();
222230
DataStore srcDataStore = Mockito.mock(DataStore.class);
223231
Mockito.doReturn(new ClusterScope(5L, 2L, 1L)).when(srcDataStore).getScope();
224232
Mockito.doReturn(srcDataStore).when(srcVolumeInfo).getDataStore();
225233
Mockito.doReturn(Storage.StoragePoolType.NetworkFilesystem).when(srcVolumeInfo).getStoragePoolType();
226234

227235
VolumeObject destVolumeInfo = Mockito.spy(new VolumeObject());
236+
Mockito.doReturn(HypervisorType.KVM).when(destVolumeInfo).getHypervisorType();
228237
DataStore destDataStore = Mockito.mock(DataStore.class);
229238
Mockito.doReturn(new ClusterScope(5L, 2L, 1L)).when(destDataStore).getScope();
230239
Mockito.doReturn(destDataStore).when(destVolumeInfo).getDataStore();
@@ -240,12 +249,14 @@ public void testCanBypassSecondaryStorageWithClusterWideNFSPoolsInSameCluster()
240249
@Test
241250
public void testCanBypassSecondaryStorageWithLocalAndClusterWideNFSPoolsInSameCluster() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
242251
VolumeObject srcVolumeInfo = Mockito.spy(new VolumeObject());
252+
Mockito.doReturn(HypervisorType.KVM).when(srcVolumeInfo).getHypervisorType();
243253
DataStore srcDataStore = Mockito.mock(DataStore.class);
244254
Mockito.doReturn(new HostScope(1L, 1L, 1L)).when(srcDataStore).getScope();
245255
Mockito.doReturn(srcDataStore).when(srcVolumeInfo).getDataStore();
246256
Mockito.doReturn(Storage.StoragePoolType.Filesystem).when(srcVolumeInfo).getStoragePoolType();
247257

248258
VolumeObject destVolumeInfo = Mockito.spy(new VolumeObject());
259+
Mockito.doReturn(HypervisorType.KVM).when(destVolumeInfo).getHypervisorType();
249260
DataStore destDataStore = Mockito.mock(DataStore.class);
250261
Mockito.doReturn(new ClusterScope(1L, 1L, 1L)).when(destDataStore).getScope();
251262
Mockito.doReturn(destDataStore).when(destVolumeInfo).getDataStore();
@@ -264,12 +275,14 @@ public void testCanBypassSecondaryStorageWithLocalAndClusterWideNFSPoolsInSameCl
264275
@Test
265276
public void testCanBypassSecondaryStorageWithLocalAndZoneWideNFSPoolsInSameZone() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
266277
VolumeObject srcVolumeInfo = Mockito.spy(new VolumeObject());
278+
Mockito.doReturn(HypervisorType.KVM).when(srcVolumeInfo).getHypervisorType();
267279
DataStore srcDataStore = Mockito.mock(DataStore.class);
268280
Mockito.doReturn(new HostScope(1L, 1L, 1L)).when(srcDataStore).getScope();
269281
Mockito.doReturn(srcDataStore).when(srcVolumeInfo).getDataStore();
270282
Mockito.doReturn(Storage.StoragePoolType.Filesystem).when(srcVolumeInfo).getStoragePoolType();
271283

272284
VolumeObject destVolumeInfo = Mockito.spy(new VolumeObject());
285+
Mockito.doReturn(HypervisorType.KVM).when(destVolumeInfo).getHypervisorType();
273286
DataStore destDataStore = Mockito.mock(DataStore.class);
274287
Mockito.doReturn(new ZoneScope(1L)).when(destDataStore).getScope();
275288
Mockito.doReturn(destDataStore).when(destVolumeInfo).getDataStore();
@@ -288,12 +301,14 @@ public void testCanBypassSecondaryStorageWithLocalAndZoneWideNFSPoolsInSameZone(
288301
@Test
289302
public void testCanBypassSecondaryStorageWithClusterWideNFSAndZoneWideNFSPoolsInSameZone() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
290303
VolumeObject srcVolumeInfo = Mockito.spy(new VolumeObject());
304+
Mockito.doReturn(HypervisorType.KVM).when(srcVolumeInfo).getHypervisorType();
291305
DataStore srcDataStore = Mockito.mock(DataStore.class);
292306
Mockito.doReturn(new ClusterScope(5L, 2L, 1L)).when(srcDataStore).getScope();
293307
Mockito.doReturn(srcDataStore).when(srcVolumeInfo).getDataStore();
294308
Mockito.doReturn(Storage.StoragePoolType.NetworkFilesystem).when(srcVolumeInfo).getStoragePoolType();
295309

296310
VolumeObject destVolumeInfo = Mockito.spy(new VolumeObject());
311+
Mockito.doReturn(HypervisorType.KVM).when(destVolumeInfo).getHypervisorType();
297312
DataStore destDataStore = Mockito.mock(DataStore.class);
298313
Mockito.doReturn(new ZoneScope(1L)).when(destDataStore).getScope();
299314
Mockito.doReturn(destDataStore).when(destVolumeInfo).getDataStore();

‎plugins/backup/nas/src/main/java/org/apache/cloudstack/backup/NASBackupProvider.java‎

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
6363
import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
6464
import org.apache.commons.collections4.CollectionUtils;
65+
import org.apache.commons.lang3.StringUtils;
6566
import org.apache.logging.log4j.Logger;
6667
import org.apache.logging.log4j.LogManager;
6768

@@ -92,16 +93,6 @@ public class NASBackupProvider extends AdapterBase implements BackupProvider, Co
9293
true,
9394
BackupFrameworkEnabled.key());
9495

95-
ConfigKey<Integer> NASBackupFullEvery = new ConfigKey<>("Advanced", Integer.class,
96-
"nas.backup.full.every",
97-
"10",
98-
"Take a full NAS backup every Nth backup; remaining backups in between are incremental. " +
99-
"Counts backups, not days, so it works for hourly, daily, and ad-hoc schedules. " +
100-
"Set to 1 to disable incrementals (every backup is full).",
101-
true,
102-
ConfigKey.Scope.Zone,
103-
BackupFrameworkEnabled.key());
104-
10596
ConfigKey<Boolean> NASBackupIncrementalEnabled = new ConfigKey<>("Advanced", Boolean.class,
10697
"nas.backup.incremental.enabled",
10798
"false",
@@ -115,6 +106,16 @@ public class NASBackupProvider extends AdapterBase implements BackupProvider, Co
115106
ConfigKey.Scope.Zone,
116107
BackupFrameworkEnabled.key());
117108

109+
ConfigKey<Integer> NASBackupFullEvery = new ConfigKey<>("Advanced", Integer.class,
110+
"nas.backup.full.every",
111+
"10",
112+
"Take a full NAS backup every Nth backup; remaining backups in between are incremental. " +
113+
"Counts backups, not days, so it works for hourly, daily, and ad-hoc schedules. " +
114+
"Set to 1 to disable incrementals (every backup is full).",
115+
true,
116+
ConfigKey.Scope.Zone,
117+
NASBackupIncrementalEnabled.key());
118+
118119
@Inject
119120
private BackupDao backupDao;
120121

@@ -392,7 +393,7 @@ private String readVmActiveCheckpoint(long vmId) {
392393
return null;
393394
}
394395
String v = d.getValue();
395-
return (v == null || v.isEmpty()) ? null : v;
396+
return StringUtils.isBlank(v) ? null : v;
396397
}
397398

398399
/**
@@ -402,7 +403,7 @@ private String readVmActiveCheckpoint(long vmId) {
402403
*/
403404
private Backup findLatestBackedUpBackup(long vmId) {
404405
List<Backup> history = backupDao.listByVmId(null, vmId);
405-
if (history == null || history.isEmpty()) {
406+
if (CollectionUtils.isEmpty(history)) {
406407
return null;
407408
}
408409
return history.stream()
@@ -434,17 +435,21 @@ private List<String> composeParentBackupPaths(Backup parent, long vmId) {
434435
// backupPath is stored as externalId by createBackupObject — e.g.
435436
// "i-2-1234-VM/2026.04.27.13.45.00".
436437
String dir = parent.getExternalId();
437-
if (dir == null || dir.isEmpty()) {
438+
if (StringUtils.isBlank(dir)) {
439+
LOG.debug("Parent backup {} has no backup path recorded; cannot compose parent backup paths", parent.getUuid());
438440
return null;
439441
}
440442

441443
List<Backup.VolumeInfo> parentVols = parent.getBackedUpVolumes();
442-
if (parentVols == null || parentVols.isEmpty()) {
444+
if (CollectionUtils.isEmpty(parentVols)) {
445+
LOG.debug("Parent backup {} has no backed up volumes recorded; cannot compose parent backup paths", parent.getUuid());
443446
return null;
444447
}
445448

446449
List<VolumeVO> currentVols = volumeDao.findByInstance(vmId);
447-
if (currentVols == null || currentVols.size() != parentVols.size()) {
450+
if (CollectionUtils.isEmpty(currentVols) || currentVols.size() != parentVols.size()) {
451+
LOG.debug("VM id={} currently has {} volume(s) but parent backup {} recorded {}; cannot compose parent backup paths",
452+
vmId, currentVols == null ? 0 : currentVols.size(), parent.getUuid(), parentVols.size());
448453
return null;
449454
}
450455

@@ -726,9 +731,12 @@ private Pair<Boolean, String> restoreVMBackup(VirtualMachine vm, Backup backup)
726731
} catch (OperationTimedoutException e) {
727732
throw new CloudRuntimeException("Operation to restore backup timed out, please try again");
728733
}
729-
// After a restore the QEMU dirty-bitmap chain is gone — clear active_checkpoint_id so
734+
if (answer == null) {
735+
throw new CloudRuntimeException(String.format("No answer received from the backend control plane while restoring VM %s from backup %s", vm.getInstanceName(), backup.getUuid()));
736+
}
737+
// After a restore the QEMU dirty-bitmap chain is gone, so clear active_checkpoint_id so
730738
// the next backup is taken as a fresh full and starts a new chain. See decideChain.
731-
if (answer != null && answer.getResult()) {
739+
if (answer.getResult()) {
732740
clearVmActiveCheckpoint(vm.getId());
733741
}
734742
return new Pair<>(answer.getResult(), answer.getDetails());

0 commit comments

Comments
 (0)