Skip to content

Commit cee330e

Browse files
author
Daan Hoogland
committed
Merge branch '4.20' into 4.22
2 parents 8936e4c + 47a6ac8 commit cee330e

File tree

17 files changed

+503
-142
lines changed

17 files changed

+503
-142
lines changed

api/src/main/java/org/apache/cloudstack/api/command/user/template/CreateTemplateCmd.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ public String getUrl() {
211211
}
212212

213213
public String getTemplateTag() {
214-
return templateTag;
214+
return StringUtils.isBlank(templateTag) ? null : templateTag;
215215
}
216216

217217
public Map getDetails() {

api/src/main/java/org/apache/cloudstack/api/command/user/template/GetUploadParamsForTemplateCmd.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ public Boolean isSshKeyEnabled() {
170170
}
171171

172172
public String getTemplateTag() {
173-
return templateTag;
173+
return StringUtils.isBlank(templateTag) ? null : templateTag;
174174
}
175175

176176
public boolean isDeployAsIs() {

api/src/main/java/org/apache/cloudstack/api/command/user/template/RegisterTemplateCmd.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ public String getChecksum() {
279279
}
280280

281281
public String getTemplateTag() {
282-
return templateTag;
282+
return StringUtils.isBlank(templateTag) ? null : templateTag;
283283
}
284284

285285
public Map getDetails() {

debian/rules

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ VERSION := $(shell grep '<version>' pom.xml | head -2 | tail -1 | cut -d'>' -f2
44
PACKAGE = $(shell dh_listpackages|head -n 1|cut -d '-' -f 1)
55
SYSCONFDIR = "/etc"
66
DESTDIR = "debian/tmp"
7-
CMK_REL := $(shell wget -O - "https://api.github.com/repos/apache/cloudstack-cloudmonkey/releases" 2>/dev/null | jq -r '.[0].tag_name')
87

98
%:
109
dh $@ --with systemd
@@ -90,7 +89,7 @@ override_dh_auto_install:
9089
rm -rf $(DESTDIR)/usr/share/$(PACKAGE)-management/templates/systemvm/sha512sum.txt
9190

9291
# Bundle cmk in cloudstack-management
93-
wget https://github.com/apache/cloudstack-cloudmonkey/releases/download/$(CMK_REL)/cmk.linux.x86-64 -O $(DESTDIR)/usr/bin/cmk
92+
wget https://github.com/apache/cloudstack-cloudmonkey/releases/latest/download/cmk.linux.x86-64 -O $(DESTDIR)/usr/bin/cmk
9493
chmod +x $(DESTDIR)/usr/bin/cmk
9594

9695
# nast hack for a couple of configuration files

engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/StorageOrchestrationService.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,18 @@
1818
package org.apache.cloudstack.engine.orchestration.service;
1919

2020
import java.util.List;
21+
import java.util.concurrent.Future;
2122

2223
import org.apache.cloudstack.api.response.MigrationResponse;
24+
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
25+
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
26+
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService.TemplateApiResult;
2327
import org.apache.cloudstack.storage.ImageStoreService.MigrationPolicy;
2428

2529
public interface StorageOrchestrationService {
2630
MigrationResponse migrateData(Long srcDataStoreId, List<Long> destDatastores, MigrationPolicy migrationPolicy);
2731

2832
MigrationResponse migrateResources(Long srcImgStoreId, Long destImgStoreId, List<Long> templateIdList, List<Long> snapshotIdList);
33+
34+
Future<TemplateApiResult> orchestrateTemplateCopyToImageStore(TemplateInfo source, DataStore destStore);
2935
}

engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/TemplateService.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,4 +78,6 @@ public TemplateInfo getTemplate() {
7878
AsyncCallFuture<TemplateApiResult> createDatadiskTemplateAsync(TemplateInfo parentTemplate, TemplateInfo dataDiskTemplate, String path, String diskId, long fileSize, boolean bootable);
7979

8080
List<DatadiskTO> getTemplateDatadisksOnImageStore(TemplateInfo templateInfo, String configurationId);
81+
82+
AsyncCallFuture<TemplateApiResult> copyTemplateToImageStore(DataObject source, DataStore destStore);
8183
}

engine/components-api/src/main/java/com/cloud/storage/StorageManager.java

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -161,22 +161,22 @@ public interface StorageManager extends StorageService {
161161
ConfigKey.Scope.StoragePool,
162162
null);
163163

164-
ConfigKey<Integer> PRIMARY_STORAGE_DOWNLOAD_WAIT = new ConfigKey<Integer>("Storage", Integer.class, "primary.storage.download.wait", "10800",
164+
ConfigKey<Integer> PRIMARY_STORAGE_DOWNLOAD_WAIT = new ConfigKey<>("Storage", Integer.class, "primary.storage.download.wait", "10800",
165165
"In second, timeout for download template to primary storage", false);
166166

167-
ConfigKey<Integer> SecStorageMaxMigrateSessions = new ConfigKey<Integer>("Advanced", Integer.class, "secstorage.max.migrate.sessions", "2",
167+
ConfigKey<Integer> SecStorageMaxMigrateSessions = new ConfigKey<>("Advanced", Integer.class, "secstorage.max.migrate.sessions", "2",
168168
"The max number of concurrent copy command execution sessions that an SSVM can handle", false, ConfigKey.Scope.Global);
169169

170-
ConfigKey<Boolean> SecStorageVMAutoScaleDown = new ConfigKey<Boolean>("Advanced", Boolean.class, "secstorage.vm.auto.scale.down", "false",
170+
ConfigKey<Boolean> SecStorageVMAutoScaleDown = new ConfigKey<>("Advanced", Boolean.class, "secstorage.vm.auto.scale.down", "false",
171171
"Setting this to 'true' will auto scale down SSVMs", true, ConfigKey.Scope.Global);
172172

173-
ConfigKey<Integer> MaxDataMigrationWaitTime = new ConfigKey<Integer>("Advanced", Integer.class, "max.data.migration.wait.time", "15",
173+
ConfigKey<Integer> MaxDataMigrationWaitTime = new ConfigKey<>("Advanced", Integer.class, "max.data.migration.wait.time", "15",
174174
"Maximum wait time (in minutes) for a data migration task before spawning a new SSVM", false, ConfigKey.Scope.Global);
175-
ConfigKey<Boolean> DiskProvisioningStrictness = new ConfigKey<Boolean>("Storage", Boolean.class, "disk.provisioning.type.strictness", "false",
175+
ConfigKey<Boolean> DiskProvisioningStrictness = new ConfigKey<>("Storage", Boolean.class, "disk.provisioning.type.strictness", "false",
176176
"If set to true, the disk is created only when there is a suitable storage pool that supports the disk provisioning type specified by the service/disk offering. " +
177177
"If set to false, the disk is created with a disk provisioning type supported by the pool. Default value is false, and this is currently supported for VMware only.",
178178
true, ConfigKey.Scope.Zone);
179-
ConfigKey<String> PreferredStoragePool = new ConfigKey<String>(String.class, "preferred.storage.pool", "Advanced", "",
179+
ConfigKey<String> PreferredStoragePool = new ConfigKey<>(String.class, "preferred.storage.pool", "Advanced", "",
180180
"The UUID of preferred storage pool for allocation.", true, ConfigKey.Scope.Account, null);
181181

182182
ConfigKey<Boolean> MountDisabledStoragePool = new ConfigKey<>(Boolean.class,
@@ -203,15 +203,15 @@ public interface StorageManager extends StorageService {
203203
true,
204204
ConfigKey.Scope.Global,
205205
null);
206-
static final ConfigKey<Boolean> DataStoreDownloadFollowRedirects = new ConfigKey<>(ConfigKey.CATEGORY_ADVANCED,
206+
ConfigKey<Boolean> DataStoreDownloadFollowRedirects = new ConfigKey<>(ConfigKey.CATEGORY_ADVANCED,
207207
Boolean.class, "store.download.follow.redirects", "false",
208208
"Whether HTTP redirect is followed during store downloads for objects such as template, volume etc.",
209209
true, ConfigKey.Scope.Global);
210210

211211
ConfigKey<Long> HEURISTICS_SCRIPT_TIMEOUT = new ConfigKey<>("Advanced", Long.class, "heuristics.script.timeout", "3000",
212212
"The maximum runtime, in milliseconds, to execute the heuristic rule; if it is reached, a timeout will happen.", true);
213213

214-
ConfigKey<Boolean> AllowVolumeReSizeBeyondAllocation = new ConfigKey<Boolean>("Advanced", Boolean.class, "volume.resize.allowed.beyond.allocation", "false",
214+
ConfigKey<Boolean> AllowVolumeReSizeBeyondAllocation = new ConfigKey<>("Advanced", Boolean.class, "volume.resize.allowed.beyond.allocation", "false",
215215
"Determines whether volume size can exceed the pool capacity allocation disable threshold (pool.storage.allocated.capacity.disablethreshold) " +
216216
"when resize a volume upto resize capacity disable threshold (pool.storage.allocated.resize.capacity.disablethreshold)",
217217
true, List.of(ConfigKey.Scope.StoragePool, ConfigKey.Scope.Zone));
@@ -228,6 +228,10 @@ public interface StorageManager extends StorageService {
228228
ConfigKey.Scope.Global,
229229
null);
230230

231+
ConfigKey<Boolean> COPY_PUBLIC_TEMPLATES_FROM_OTHER_STORAGES = new ConfigKey<>(Boolean.class, "copy.public.templates.from.other.storages",
232+
"Storage", "true", "Allow SSVMs to try copying public templates from one secondary storage to another instead of downloading them from the source.",
233+
true, ConfigKey.Scope.Zone, null);
234+
231235
/**
232236
* should we execute in sequence not involving any storages?
233237
* @return tru if commands should execute in sequence
@@ -252,14 +256,14 @@ static Boolean getFullCloneConfiguration(Long storeId) {
252256

253257
/**
254258
* Returns a comma separated list of tags for the specified storage pool
255-
* @param poolId
259+
* @param poolId the id of the pool to get tags for
256260
* @return comma separated list of tags
257261
*/
258262
String getStoragePoolTags(long poolId);
259263

260264
/**
261265
* Returns a list of Strings with tags for the specified storage pool
262-
* @param poolId
266+
* @param poolId the id of the pool to get tags for
263267
* @return comma separated list of tags
264268
*/
265269
List<String> getStoragePoolTagList(long poolId);
@@ -276,7 +280,7 @@ static Boolean getFullCloneConfiguration(Long storeId) {
276280

277281
Pair<Long, Answer> sendToPool(StoragePool pool, long[] hostIdsToTryFirst, List<Long> hostIdsToAvoid, Command cmd) throws StorageUnavailableException;
278282

279-
public Answer getVolumeStats(StoragePool pool, Command cmd);
283+
Answer getVolumeStats(StoragePool pool, Command cmd);
280284

281285
boolean canPoolProvideStorageStats(StoragePool pool);
282286

engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/DataMigrationUtility.java

Lines changed: 70 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,12 @@
2222
import java.util.Collections;
2323
import java.util.Comparator;
2424
import java.util.HashMap;
25+
import java.util.HashSet;
2526
import java.util.LinkedHashMap;
2627
import java.util.LinkedList;
2728
import java.util.List;
2829
import java.util.Map;
30+
import java.util.Set;
2931

3032
import javax.inject.Inject;
3133

@@ -206,12 +208,22 @@ public int compare(DataObject o1, DataObject o2) {
206208

207209
protected List<DataObject> getAllReadyTemplates(DataStore srcDataStore, Map<DataObject, Pair<List<TemplateInfo>, Long>> childTemplates, List<TemplateDataStoreVO> templates) {
208210
List<TemplateInfo> files = new LinkedList<>();
211+
Set<Long> idsForMigration = new HashSet<>();
212+
209213
for (TemplateDataStoreVO template : templates) {
210-
VMTemplateVO templateVO = templateDao.findById(template.getTemplateId());
211-
if (shouldMigrateTemplate(template, templateVO)) {
212-
files.add(templateFactory.getTemplate(template.getTemplateId(), srcDataStore));
214+
long templateId = template.getTemplateId();
215+
if (idsForMigration.contains(templateId)) {
216+
logger.warn("Template store reference [{}] is duplicated; not considering it for migration.", template);
217+
continue;
218+
}
219+
VMTemplateVO templateVO = templateDao.findById(templateId);
220+
if (!shouldMigrateTemplate(template, templateVO)) {
221+
continue;
213222
}
223+
files.add(templateFactory.getTemplate(template.getTemplateId(), srcDataStore));
224+
idsForMigration.add(templateId);
214225
}
226+
215227
for (TemplateInfo template: files) {
216228
List<VMTemplateVO> children = templateDao.listByParentTemplatetId(template.getId());
217229
List<TemplateInfo> temps = new ArrayList<>();
@@ -221,6 +233,7 @@ protected List<DataObject> getAllReadyTemplates(DataStore srcDataStore, Map<Data
221233
}
222234
childTemplates.put(template, new Pair<>(temps, getTotalChainSize(temps)));
223235
}
236+
224237
return (List<DataObject>) (List<?>) files;
225238
}
226239

@@ -263,16 +276,37 @@ protected boolean shouldMigrateTemplate(TemplateDataStoreVO template, VMTemplate
263276
*/
264277
protected List<DataObject> getAllReadySnapshotsAndChains(DataStore srcDataStore, Map<DataObject, Pair<List<SnapshotInfo>, Long>> snapshotChains, List<SnapshotDataStoreVO> snapshots) {
265278
List<SnapshotInfo> files = new LinkedList<>();
279+
Set<Long> idsForMigration = new HashSet<>();
280+
266281
for (SnapshotDataStoreVO snapshot : snapshots) {
267-
SnapshotVO snapshotVO = snapshotDao.findById(snapshot.getSnapshotId());
268-
if (snapshot.getState() == ObjectInDataStoreStateMachine.State.Ready &&
269-
snapshotVO != null && snapshotVO.getHypervisorType() != Hypervisor.HypervisorType.Simulator
270-
&& snapshot.getParentSnapshotId() == 0 ) {
271-
SnapshotInfo snap = snapshotFactory.getSnapshot(snapshotVO.getSnapshotId(), snapshot.getDataStoreId(), snapshot.getRole());
272-
if (snap != null) {
273-
files.add(snap);
274-
}
282+
long snapshotId = snapshot.getSnapshotId();
283+
if (idsForMigration.contains(snapshotId)) {
284+
logger.warn("Snapshot store reference [{}] is duplicated; not considering it for migration.", snapshot);
285+
continue;
286+
}
287+
if (snapshot.getState() != ObjectInDataStoreStateMachine.State.Ready) {
288+
logger.warn("Not migrating snapshot [{}] because its state is not ready.", snapshot);
289+
continue;
290+
}
291+
SnapshotVO snapshotVO = snapshotDao.findById(snapshotId);
292+
if (snapshotVO == null) {
293+
logger.debug("Not migrating snapshot [{}] because we could not find its database entry.", snapshot);
294+
continue;
295+
}
296+
if (snapshotVO.getHypervisorType() == Hypervisor.HypervisorType.Simulator) {
297+
logger.debug("Not migrating snapshot [{}] because its hypervisor type is simulator.", snapshot);
298+
continue;
275299
}
300+
if (snapshot.getParentSnapshotId() != 0) {
301+
continue; // The child snapshot will be migrated in the for loop below.
302+
}
303+
SnapshotInfo snap = snapshotFactory.getSnapshot(snapshotVO.getSnapshotId(), snapshot.getDataStoreId(), snapshot.getRole());
304+
if (snap == null) {
305+
logger.debug("Not migrating snapshot [{}] because we could not get its information.", snapshot);
306+
continue;
307+
}
308+
files.add(snap);
309+
idsForMigration.add(snapshotId);
276310
}
277311

278312
for (SnapshotInfo parent : files) {
@@ -285,7 +319,7 @@ protected List<DataObject> getAllReadySnapshotsAndChains(DataStore srcDataStore,
285319
chain.addAll(children);
286320
}
287321
}
288-
snapshotChains.put(parent, new Pair<List<SnapshotInfo>, Long>(chain, getTotalChainSize(chain)));
322+
snapshotChains.put(parent, new Pair<>(chain, getTotalChainSize(chain)));
289323
}
290324

291325
return (List<DataObject>) (List<?>) files;
@@ -306,14 +340,31 @@ protected Long getTotalChainSize(List<? extends DataObject> chain) {
306340

307341
protected List<DataObject> getAllReadyVolumes(DataStore srcDataStore, List<VolumeDataStoreVO> volumes) {
308342
List<DataObject> files = new LinkedList<>();
343+
Set<Long> idsForMigration = new HashSet<>();
344+
309345
for (VolumeDataStoreVO volume : volumes) {
310-
if (volume.getState() == ObjectInDataStoreStateMachine.State.Ready) {
311-
VolumeInfo volumeInfo = volumeFactory.getVolume(volume.getVolumeId(), srcDataStore);
312-
if (volumeInfo != null && volumeInfo.getHypervisorType() != Hypervisor.HypervisorType.Simulator) {
313-
files.add(volumeInfo);
314-
}
346+
long volumeId = volume.getVolumeId();
347+
if (idsForMigration.contains(volumeId)) {
348+
logger.warn("Volume store reference [{}] is duplicated; not considering it for migration.", volume);
349+
continue;
315350
}
351+
if (volume.getState() != ObjectInDataStoreStateMachine.State.Ready) {
352+
logger.debug("Not migrating volume [{}] because its state is not ready.", volume);
353+
continue;
354+
}
355+
VolumeInfo volumeInfo = volumeFactory.getVolume(volume.getVolumeId(), srcDataStore);
356+
if (volumeInfo == null) {
357+
logger.debug("Not migrating volume [{}] because we could not get its information.", volume);
358+
continue;
359+
}
360+
if (volumeInfo.getHypervisorType() == Hypervisor.HypervisorType.Simulator) {
361+
logger.debug("Not migrating volume [{}] because its hypervisor type is simulator.", volume);
362+
continue;
363+
}
364+
files.add(volumeInfo);
365+
idsForMigration.add(volumeId);
316366
}
367+
317368
return files;
318369
}
319370

@@ -325,10 +376,9 @@ protected List<DataObject> getAllReadyVolumes(DataStore srcDataStore) {
325376
/** Returns the count of active SSVMs - SSVM with agents in connected state, so as to dynamically increase the thread pool
326377
* size when SSVMs scale
327378
*/
328-
protected int activeSSVMCount(DataStore dataStore) {
329-
long datacenterId = dataStore.getScope().getScopeId();
379+
protected int activeSSVMCount(Long zoneId) {
330380
List<SecondaryStorageVmVO> ssvms =
331-
secStorageVmDao.getSecStorageVmListInStates(null, datacenterId, VirtualMachine.State.Running, VirtualMachine.State.Migrating);
381+
secStorageVmDao.getSecStorageVmListInStates(null, zoneId, VirtualMachine.State.Running, VirtualMachine.State.Migrating);
332382
int activeSSVMs = 0;
333383
for (SecondaryStorageVmVO vm : ssvms) {
334384
String name = "s-"+vm.getId()+"-VM";

0 commit comments

Comments
 (0)