Skip to content

Commit d8890ec

Browse files
committed
fix revert snapshot format type and handle revert snapshot functionality for clvm
1 parent 7b5af5e commit d8890ec

File tree

5 files changed

+119
-5
lines changed

5 files changed

+119
-5
lines changed

engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@
258258
import com.cloud.storage.Volume.Type;
259259
import com.cloud.storage.VolumeApiService;
260260
import com.cloud.storage.VolumeApiServiceImpl;
261+
import com.cloud.storage.VolumeDetailVO;
261262
import com.cloud.storage.VolumeVO;
262263
import com.cloud.storage.dao.DiskOfferingDao;
263264
import com.cloud.storage.dao.GuestOSCategoryDao;
@@ -266,6 +267,7 @@
266267
import com.cloud.storage.dao.VMTemplateDao;
267268
import com.cloud.storage.dao.VMTemplateZoneDao;
268269
import com.cloud.storage.dao.VolumeDao;
270+
import com.cloud.storage.dao.VolumeDetailsDao;
269271
import com.cloud.storage.snapshot.SnapshotManager;
270272
import com.cloud.template.VirtualMachineTemplate;
271273
import com.cloud.user.Account;
@@ -361,6 +363,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
361363
@Inject
362364
private VolumeDao _volsDao;
363365
@Inject
366+
private VolumeDetailsDao _volsDetailsDao;
367+
@Inject
364368
private HighAvailabilityManager _haMgr;
365369
@Inject
366370
private HostPodDao _podDao;
@@ -3274,6 +3278,8 @@ protected void migrate(final VMInstanceVO vm, final long srcHostId, final Deploy
32743278
logger.warn("Exception during post-migration tasks for VM {} on destination host {}: {}. Migration completed but some cleanup may be needed.",
32753279
vm.getInstanceName(), dstHostId, e.getMessage(), e);
32763280
}
3281+
3282+
updateClvmLockHostForVmVolumes(vm.getId(), dstHostId);
32773283
} finally {
32783284
if (!migrated) {
32793285
logger.info("Migration was unsuccessful. Cleaning up: {}", vm);
@@ -3359,6 +3365,37 @@ private void updateVmPod(VMInstanceVO vm, long dstHostId) {
33593365
_vmDao.persist(newVm);
33603366
}
33613367

3368+
/**
3369+
* Updates CLVM_LOCK_HOST_ID for all CLVM volumes attached to a VM after VM migration.
3370+
* This ensures that subsequent operations on CLVM volumes are routed to the correct host.
3371+
*
3372+
* @param vmId The ID of the VM that was migrated
3373+
* @param destHostId The destination host ID where the VM now resides
3374+
*/
3375+
private void updateClvmLockHostForVmVolumes(long vmId, long destHostId) {
3376+
List<VolumeVO> volumes = _volsDao.findByInstance(vmId);
3377+
if (volumes == null || volumes.isEmpty()) {
3378+
return;
3379+
}
3380+
3381+
for (VolumeVO volume : volumes) {
3382+
StoragePoolVO pool = _storagePoolDao.findById(volume.getPoolId());
3383+
if (pool != null && pool.getPoolType() == Storage.StoragePoolType.CLVM) {
3384+
VolumeDetailVO existingDetail = _volsDetailsDao.findDetail(volume.getId(), VolumeInfo.CLVM_LOCK_HOST_ID);
3385+
if (existingDetail != null) {
3386+
existingDetail.setValue(String.valueOf(destHostId));
3387+
_volsDetailsDao.update(existingDetail.getId(), existingDetail);
3388+
logger.debug("Updated CLVM_LOCK_HOST_ID for volume {} to host {} after VM {} migration",
3389+
volume.getUuid(), destHostId, vmId);
3390+
} else {
3391+
_volsDetailsDao.addDetail(volume.getId(), VolumeInfo.CLVM_LOCK_HOST_ID, String.valueOf(destHostId), false);
3392+
logger.debug("Created CLVM_LOCK_HOST_ID for volume {} with host {} after VM {} migration",
3393+
volume.getUuid(), destHostId, vmId);
3394+
}
3395+
}
3396+
}
3397+
}
3398+
33623399
/**
33633400
* We create the mapping of volumes and storage pool to migrate the VMs according to the information sent by the user.
33643401
* If the user did not enter a complete mapping, the volumes that were left behind will be auto mapped using {@link #createStoragePoolMappingsForVolumes(VirtualMachineProfile, DataCenterDeployment, Map, List)}

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

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -819,6 +819,39 @@ private void setClvmLockHostId(long volumeId, long hostId) {
819819
}
820820
}
821821

822+
/**
823+
* Updates the CLVM_LOCK_HOST_ID for a migrated volume if applicable.
824+
* For CLVM volumes that are attached to a VM, this updates the lock host tracking
825+
* to point to the VM's current host after volume migration.
826+
*
827+
* @param migratedVolume The volume that was migrated
828+
* @param destPool The destination storage pool
829+
* @param operationType Description of the operation (e.g., "migrated", "live-migrated") for logging
830+
*/
831+
private void updateClvmLockHostAfterMigration(Volume migratedVolume, StoragePool destPool, String operationType) {
832+
if (migratedVolume == null || destPool == null) {
833+
return;
834+
}
835+
836+
StoragePoolVO pool = _storagePoolDao.findById(destPool.getId());
837+
if (pool == null || pool.getPoolType() != Storage.StoragePoolType.CLVM) {
838+
return;
839+
}
840+
841+
if (migratedVolume.getInstanceId() == null) {
842+
return;
843+
}
844+
845+
VMInstanceVO vm = vmInstanceDao.findById(migratedVolume.getInstanceId());
846+
if (vm == null || vm.getHostId() == null) {
847+
return;
848+
}
849+
850+
setClvmLockHostId(migratedVolume.getId(), vm.getHostId());
851+
logger.debug("Updated CLVM_LOCK_HOST_ID for {} volume {} to host {} where VM {} is running",
852+
operationType, migratedVolume.getUuid(), vm.getHostId(), vm.getInstanceName());
853+
}
854+
822855
public String getRandomVolumeName() {
823856
return UUID.randomUUID().toString();
824857
}
@@ -1485,6 +1518,9 @@ public Volume migrateVolume(Volume volume, StoragePool destPool) throws StorageU
14851518
_snapshotDao.updateVolumeIds(vol.getId(), result.getVolume().getId());
14861519
_snapshotDataStoreDao.updateVolumeIds(vol.getId(), result.getVolume().getId());
14871520
}
1521+
1522+
// For CLVM volumes attached to a VM, update the CLVM_LOCK_HOST_ID after migration
1523+
updateClvmLockHostAfterMigration(result.getVolume(), destPool, "migrated");
14881524
}
14891525
return result.getVolume();
14901526
} catch (InterruptedException | ExecutionException e) {
@@ -1510,6 +1546,10 @@ public Volume liveMigrateVolume(Volume volume, StoragePool destPool) {
15101546
logger.error("Volume [{}] migration failed due to [{}].", volToString, result.getResult());
15111547
return null;
15121548
}
1549+
1550+
// For CLVM volumes attached to a VM, update the CLVM_LOCK_HOST_ID after live migration
1551+
updateClvmLockHostAfterMigration(result.getVolume(), destPool, "live-migrated");
1552+
15131553
return result.getVolume();
15141554
} catch (InterruptedException | ExecutionException e) {
15151555
logger.error("Volume [{}] migration failed due to [{}].", volToString, e.getMessage());
@@ -1552,6 +1592,11 @@ public void migrateVolumes(VirtualMachine vm, VirtualMachineTO vmTo, Host srcHos
15521592
logger.error(msg);
15531593
throw new CloudRuntimeException(msg);
15541594
}
1595+
for (Map.Entry<Volume, StoragePool> entry : volumeToPool.entrySet()) {
1596+
Volume volume = entry.getKey();
1597+
StoragePool destPool = entry.getValue();
1598+
updateClvmLockHostAfterMigration(volume, destPool, "vm-migrated");
1599+
}
15551600
} catch (InterruptedException | ExecutionException e) {
15561601
logger.error("Failed to migrate VM [{}] along with its volumes due to [{}].", vm, e.getMessage());
15571602
logger.debug("Exception: ", e);

engine/storage/src/main/java/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,26 @@ public EndPoint select(DataObject object, boolean encryptionSupportRequired) {
470470
@Override
471471
public EndPoint select(DataObject object) {
472472
DataStore store = object.getDataStore();
473+
474+
// For CLVM volumes, check if there's a lock host ID to route to
475+
if (object instanceof VolumeInfo && store.getRole() == DataStoreRole.Primary) {
476+
VolumeInfo volume = (VolumeInfo) object;
477+
StoragePoolVO pool = _storagePoolDao.findById(store.getId());
478+
if (pool != null && pool.getPoolType() == Storage.StoragePoolType.CLVM) {
479+
Long lockHostId = getClvmLockHostId(volume);
480+
if (lockHostId != null) {
481+
logger.debug("Routing CLVM volume {} operation to lock holder host {}",
482+
volume.getUuid(), lockHostId);
483+
EndPoint ep = getEndPointFromHostId(lockHostId);
484+
if (ep != null) {
485+
return ep;
486+
}
487+
logger.warn("Could not get endpoint for CLVM lock host {}, falling back to default selection",
488+
lockHostId);
489+
}
490+
}
491+
}
492+
473493
EndPoint ep = select(store);
474494
if (ep != null) {
475495
return ep;

plugins/storage/volume/default/src/main/java/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -422,12 +422,19 @@ public void revertSnapshot(SnapshotInfo snapshot, SnapshotInfo snapshotOnPrimary
422422
CommandResult result = new CommandResult();
423423
try {
424424
EndPoint ep = null;
425-
if (snapshotOnPrimaryStore != null) {
426-
ep = epSelector.select(snapshotOnPrimaryStore);
427-
} else {
428-
VolumeInfo volumeInfo = volFactory.getVolume(snapshot.getVolumeId(), DataStoreRole.Primary);
425+
VolumeInfo volumeInfo = volFactory.getVolume(snapshot.getVolumeId(), DataStoreRole.Primary);
426+
427+
StoragePoolVO storagePool = primaryStoreDao.findById(volumeInfo.getPoolId());
428+
if (storagePool != null && storagePool.getPoolType() == StoragePoolType.CLVM) {
429429
ep = epSelector.select(volumeInfo);
430+
} else {
431+
if (snapshotOnPrimaryStore != null) {
432+
ep = epSelector.select(snapshotOnPrimaryStore);
433+
} else {
434+
ep = epSelector.select(volumeInfo);
435+
}
430436
}
437+
431438
if ( ep == null ){
432439
String errMsg = "No remote endpoint to send RevertSnapshotCommand, check if host or ssvm is down?";
433440
logger.error(errMsg);

scripts/storage/qcow2/managesnapshot.sh

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,12 @@ backup_snapshot() {
307307
revert_snapshot() {
308308
local snapshotPath=$1
309309
local destPath=$2
310-
${qemu_img} convert -f qcow2 -O qcow2 "$snapshotPath" "$destPath" || \
310+
local output_format="qcow2"
311+
if [ -b "$destPath" ]; then
312+
output_format="raw"
313+
fi
314+
315+
${qemu_img} convert -f qcow2 -O ${output_format} "$snapshotPath" "$destPath" || \
311316
( printf "${qemu_img} failed to revert snapshot ${snapshotPath} to disk ${destPath}.\n" >&2; return 2 )
312317
return 0
313318
}

0 commit comments

Comments
 (0)