Skip to content

Commit e8200a0

Browse files
authored
Prioritize copying templates from other secondary storages instead of downloading them (#10363)
* Prioritize copying templates from other secondary storages instead of downloading them * Treat some corner cases
1 parent ba26d95 commit e8200a0

File tree

8 files changed

+440
-100
lines changed

8 files changed

+440
-100
lines changed

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: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,10 @@ public interface StorageManager extends StorageService {
220220
"storage.pool.host.connect.workers", "1",
221221
"Number of worker threads to be used to connect hosts to a primary storage", true);
222222

223+
ConfigKey<Boolean> COPY_PUBLIC_TEMPLATES_FROM_OTHER_STORAGES = new ConfigKey<>(Boolean.class, "copy.public.templates.from.other.storages",
224+
"Storage", "true", "Allow SSVMs to try copying public templates from one secondary storage to another instead of downloading them from the source.",
225+
true, ConfigKey.Scope.Zone, null);
226+
223227
/**
224228
* should we execute in sequence not involving any storages?
225229
* @return tru if commands should execute in sequence

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)