Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Fix restore/attach backup volume as RBD volume in Ceph storage pool
  • Loading branch information
sureshanaparti committed Sep 26, 2025
commit 792b80fefb909196162e3a5a0e73820c752f2654
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
import com.cloud.storage.DataStoreRole;
import com.cloud.storage.ScopeType;
import com.cloud.storage.Storage;
import com.cloud.storage.StoragePoolHostVO;
import com.cloud.storage.Volume;
import com.cloud.storage.VolumeApiServiceImpl;
import com.cloud.storage.VolumeVO;
Expand Down Expand Up @@ -337,9 +336,11 @@ private Pair<List<PrimaryDataStoreTO>, List<String>> getVolumePoolsAndPaths(List
if (Objects.isNull(storagePool)) {
throw new CloudRuntimeException("Unable to find storage pool associated to the volume");
}
String volumePathPrefix = getVolumePathPrefix(storagePool);

DataStore dataStore = dataStoreMgr.getDataStore(storagePool.getId(), DataStoreRole.Primary);
volumePools.add(dataStore != null ? (PrimaryDataStoreTO)dataStore.getTO() : null);

String volumePathPrefix = getVolumePathPrefix(storagePool);
volumePaths.add(String.format("%s/%s", volumePathPrefix, volume.getPath()));
}
return new Pair<>(volumePools, volumePaths);
Expand All @@ -364,7 +365,6 @@ public Pair<Boolean, String> restoreBackedUpVolume(Backup backup, Backup.VolumeI
final DiskOffering diskOffering = diskOfferingDao.findByUuid(backupVolumeInfo.getDiskOfferingId());
final StoragePoolVO pool = primaryDataStoreDao.findByUuid(dataStoreUuid);
final HostVO hostVO = hostDao.findByIp(hostIp);
final StoragePoolHostVO storagePoolHost = storagePoolHostDao.findByPoolHost(pool.getId(), hostVO.getId());

LOG.debug("Restoring vm volume {} from backup {} on the NAS Backup Provider", backupVolumeInfo, backup);
BackupRepository backupRepository = getBackupRepository(backup);
Expand Down Expand Up @@ -396,7 +396,7 @@ public Pair<Boolean, String> restoreBackedUpVolume(Backup backup, Backup.VolumeI
restoreCommand.setBackupRepoType(backupRepository.getType());
restoreCommand.setBackupRepoAddress(backupRepository.getAddress());
restoreCommand.setVmName(vmNameAndState.first());
restoreCommand.setRestoreVolumePaths(Collections.singletonList(String.format("%s%s", storagePoolHost != null ? storagePoolHost.getLocalPath() + "/" : "", volumeUUID)));
restoreCommand.setRestoreVolumePaths(Collections.singletonList(String.format("%s/%s", getVolumePathPrefix(pool), volumeUUID)));
DataStore dataStore = dataStoreMgr.getDataStore(pool.getId(), DataStoreRole.Primary);
restoreCommand.setRestoreVolumePools(Collections.singletonList(dataStore != null ? (PrimaryDataStoreTO)dataStore.getTO() : null));
restoreCommand.setDiskType(backupVolumeInfo.getType().name().toLowerCase(Locale.ROOT));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ public class LibvirtRestoreBackupCommandWrapper extends CommandWrapper<RestoreBa
private static final String UMOUNT_COMMAND = "sudo umount %s";
private static final String FILE_PATH_PLACEHOLDER = "%s/%s";
private static final String ATTACH_QCOW2_DISK_COMMAND = " virsh attach-disk %s %s %s --driver qemu --subdriver qcow2 --cache none";
private static final String ATTACH_RBD_DISK_COMMAND = " virsh attach-disk %s /dev/null %s --driver qemu --subdriver raw --type network --source-protocol rbd --source-name %s --cache none";
private static final String ATTACH_RBD_DISK_XML_COMMAND = " virsh attach-device %s /dev/stdin <<EOF%sEOF";
private static final String CURRRENT_DEVICE = "virsh domblklist --domain %s | tail -n 3 | head -n 1 | awk '{print $1}'";
private static final String RSYNC_COMMAND = "rsync -az %s %s";
Expand Down Expand Up @@ -156,7 +155,7 @@ private void restoreVolume(KVMStoragePoolManager storagePoolMgr, String backupPa
try {
bkpPathAndVolUuid = getBackupPath(mountDirectory, volumePath, backupPath, diskType, volumeUUID);
verifyBackupFile(bkpPathAndVolUuid.first(), bkpPathAndVolUuid.second());
if (!replaceVolumeWithBackup(storagePoolMgr, volumePool, volumePath, bkpPathAndVolUuid.first(), timeout)) {
if (!replaceVolumeWithBackup(storagePoolMgr, volumePool, volumePath, bkpPathAndVolUuid.first(), timeout, true)) {
throw new CloudRuntimeException(String.format("Unable to restore contents from the backup volume [%s].", bkpPathAndVolUuid.second()));
}
if (VirtualMachine.State.Running.equals(vmNameAndState.second())) {
Expand Down Expand Up @@ -239,28 +238,34 @@ private boolean checkBackupPathExists(String backupPath) {
}

private boolean replaceVolumeWithBackup(KVMStoragePoolManager storagePoolMgr, PrimaryDataStoreTO volumePool, String volumePath, String backupPath, int timeout) {
return replaceVolumeWithBackup(storagePoolMgr, volumePool, volumePath, backupPath, timeout, false);
}

private boolean replaceVolumeWithBackup(KVMStoragePoolManager storagePoolMgr, PrimaryDataStoreTO volumePool, String volumePath, String backupPath, int timeout, boolean createTargetVolume) {
if (volumePool.getPoolType() != Storage.StoragePoolType.RBD) {
int exitValue = Script.runSimpleBashScriptForExitValue(String.format(RSYNC_COMMAND, backupPath, volumePath));
return exitValue == 0;
}

return replaceRbdVolumeWithBackup(storagePoolMgr, volumePool, volumePath, backupPath, timeout);
return replaceRbdVolumeWithBackup(storagePoolMgr, volumePool, volumePath, backupPath, timeout, createTargetVolume);
}

private boolean replaceRbdVolumeWithBackup(KVMStoragePoolManager storagePoolMgr, PrimaryDataStoreTO volumePool, String volumePath, String backupPath, int timeout) {
private boolean replaceRbdVolumeWithBackup(KVMStoragePoolManager storagePoolMgr, PrimaryDataStoreTO volumePool, String volumePath, String backupPath, int timeout, boolean createTargetVolume) {
KVMStoragePool volumeStoragePool = storagePoolMgr.getStoragePool(volumePool.getPoolType(), volumePool.getUuid());
KVMPhysicalDisk rdbDisk = volumeStoragePool.getPhysicalDisk(volumePath);
logger.debug("RBD volume: {}", rdbDisk.toString());
QemuImg qemu;
try {
qemu = new QemuImg(timeout * 1000, true, false);
qemu.setSkipTargetVolumeCreation(true);
if (!createTargetVolume) {
KVMPhysicalDisk rdbDisk = volumeStoragePool.getPhysicalDisk(volumePath);
logger.debug("RBD volume: {}", rdbDisk.toString());
Comment thread
sureshanaparti marked this conversation as resolved.
Outdated
qemu.setSkipTargetVolumeCreation(true);
}
} catch (LibvirtException ex) {
throw new CloudRuntimeException("Failed to create qemu-img command to replace RBD volume with backup", ex);
}

QemuImgFile srcBackupFile = null;
QemuImgFile destVolumeFile = null;

try {
srcBackupFile = new QemuImgFile(backupPath, QemuImg.PhysicalDiskFormat.QCOW2);
String rbdDestVolumeFile = KVMPhysicalDisk.RBDStringBuilder(volumeStoragePool, volumePath);
Expand All @@ -285,7 +290,6 @@ private boolean attachVolumeToVm(KVMStoragePoolManager storagePoolMgr, String vm
if (volumePool.getPoolType() != Storage.StoragePoolType.RBD) {
exitValue = Script.runSimpleBashScriptForExitValue(String.format(ATTACH_QCOW2_DISK_COMMAND, vmName, volumePath, deviceToAttachDiskTo));
} else {
// exitValue = Script.runSimpleBashScriptForExitValue(String.format(ATTACH_RBD_DISK_COMMAND, vmName, deviceToAttachDiskTo, volumePath));
String xmlForRbdDisk = getXmlForRbdDisk(storagePoolMgr, volumePool, volumePath, deviceToAttachDiskTo);
logger.debug("RBD disk xml to attach: {}", xmlForRbdDisk);
exitValue = Script.runSimpleBashScriptForExitValue(String.format(ATTACH_RBD_DISK_XML_COMMAND, vmName, xmlForRbdDisk));
Expand Down