Consider secondary storage selectors during cold volume migration (#10957)

The secondary storage selectors allow operators to specify, for instance, that volumes should go to a specific secondary storage A. Thus, when uploading a volume, it will always be downloaded to secondary storage A.

The cold volume migration moves volumes to a secondary storage before moving them to the destination primary storage. This process does not consider the secondary storage selectors. However, some companies want to dedicate specific secondary storages for cold migration.

To address this, this PR makes the cold volume migration process consider the secondary storage selectors.
This commit is contained in:
Fabricio Duarte 2026-01-28 02:48:31 -03:00 committed by GitHub
parent dd0b863e22
commit 70d4c9d1ba
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 20 additions and 9 deletions

View File

@ -45,10 +45,12 @@ import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.secstorage.heuristics.HeuristicType;
import org.apache.cloudstack.storage.RemoteHostEndPoint;
import org.apache.cloudstack.storage.command.CopyCommand;
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreVO;
import org.apache.cloudstack.storage.heuristics.HeuristicRuleHelper;
import org.apache.cloudstack.storage.image.datastore.ImageStoreEntity;
import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
import org.apache.logging.log4j.Logger;
@ -104,6 +106,9 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
@Inject
SnapshotDao snapshotDao;
@Inject
HeuristicRuleHelper heuristicRuleHelper;
@Override
public StrategyPriority canHandle(DataObject srcData, DataObject destData) {
return StrategyPriority.DEFAULT;
@ -374,7 +379,13 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
}
// need to find a nfs or cifs image store, assuming that can't copy volume
// directly to s3
ImageStoreEntity imageStore = (ImageStoreEntity)dataStoreMgr.getImageStoreWithFreeCapacity(destScope.getScopeId());
Long zoneId = destScope.getScopeId();
ImageStoreEntity imageStore = (ImageStoreEntity) heuristicRuleHelper.getImageStoreIfThereIsHeuristicRule(zoneId, HeuristicType.VOLUME, destData);
if (imageStore == null) {
logger.debug("Secondary storage selector did not direct volume migration to a specific secondary storage; using secondary storage with the most free capacity.");
imageStore = (ImageStoreEntity) dataStoreMgr.getImageStoreWithFreeCapacity(zoneId);
}
if (imageStore == null || !imageStore.getProtocol().equalsIgnoreCase("nfs") && !imageStore.getProtocol().equalsIgnoreCase("cifs")) {
String errMsg = "can't find a nfs (or cifs) image store to satisfy the need for a staging store";
Answer answer = new Answer(null, false, errMsg);

View File

@ -117,8 +117,8 @@ public class HeuristicRuleHelper {
accountId = ((SnapshotInfo) obj).getAccountId();
break;
case VOLUME:
presetVariables.setVolume(setVolumePresetVariable((VolumeVO) obj));
accountId = ((VolumeVO) obj).getAccountId();
presetVariables.setVolume(setVolumePresetVariable((com.cloud.storage.Volume) obj));
accountId = ((com.cloud.storage.Volume) obj).getAccountId();
break;
}
presetVariables.setAccount(setAccountPresetVariable(accountId));
@ -191,14 +191,14 @@ public class HeuristicRuleHelper {
return template;
}
protected Volume setVolumePresetVariable(VolumeVO volumeVO) {
Volume volume = new Volume();
protected Volume setVolumePresetVariable(com.cloud.storage.Volume volumeVO) {
Volume volumePresetVariable = new Volume();
volume.setName(volumeVO.getName());
volume.setFormat(volumeVO.getFormat());
volume.setSize(volumeVO.getSize());
volumePresetVariable.setName(volumeVO.getName());
volumePresetVariable.setFormat(volumeVO.getFormat());
volumePresetVariable.setSize(volumeVO.getSize());
return volume;
return volumePresetVariable;
}
protected Snapshot setSnapshotPresetVariable(SnapshotInfo snapshotInfo) {