diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java index 074d0af1ad3..4cb356c8023 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java @@ -56,6 +56,9 @@ import org.apache.cloudstack.utils.hypervisor.HypervisorUtils; import org.apache.cloudstack.utils.linux.CPUStat; import org.apache.cloudstack.utils.linux.KVMHostInfo; import org.apache.cloudstack.utils.linux.MemStat; +import org.apache.cloudstack.utils.qemu.QemuImg; +import org.apache.cloudstack.utils.qemu.QemuImgException; +import org.apache.cloudstack.utils.qemu.QemuImgFile; import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat; import org.apache.cloudstack.utils.security.KeyStoreUtils; import org.apache.commons.collections.MapUtils; @@ -2528,6 +2531,15 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv volPath = physicalDisk.getPath(); } + if (volume.getType() != Volume.Type.ISO + && physicalDisk != null && physicalDisk.getFormat() == PhysicalDiskFormat.QCOW2 + && (pool.getType() == StoragePoolType.NetworkFilesystem + || pool.getType() == StoragePoolType.SharedMountPoint + || pool.getType() == StoragePoolType.Filesystem + || pool.getType() == StoragePoolType.Gluster)) { + setBackingFileFormat(physicalDisk.getPath()); + } + // check for disk activity, if detected we should exit because vm is running elsewhere if (_diskActivityCheckEnabled && physicalDisk != null && physicalDisk.getFormat() == PhysicalDiskFormat.QCOW2) { s_logger.debug("Checking physical disk file at path " + volPath + " for disk activity to ensure vm is not running elsewhere"); @@ -4245,4 +4257,25 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv cmd.setTopology(numCoresPerSocket, vcpus / numCoresPerSocket); } } + + public void setBackingFileFormat(String volPath) { + final int timeout = 0; + QemuImgFile file = new QemuImgFile(volPath); + QemuImg qemu = new QemuImg(timeout); + try{ + Map info = qemu.info(file); + String backingFilePath = info.get(new String("backing_file")); + String backingFileFormat = info.get(new String("backing_file_format")); + if (org.apache.commons.lang.StringUtils.isEmpty(backingFileFormat)) { + s_logger.info("Setting backing file format of " + volPath); + QemuImgFile backingFile = new QemuImgFile(backingFilePath); + Map backingFileinfo = qemu.info(backingFile); + String backingFileFmt = backingFileinfo.get(new String("file_format")); + qemu.rebase(file, backingFile, backingFileFmt, false); + } + } catch (QemuImgException e) { + s_logger.error("Failed to set backing file format of " + volPath + " due to : " + e.getMessage()); + } + } + } diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapper.java index 0524be79617..841eadf13c2 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapper.java @@ -155,6 +155,14 @@ public final class LibvirtMigrateCommandWrapper extends CommandWrapper mapMigrateStorage = command.getMigrateStorage(); // migrateStorage is declared as final because the replaceStorage method may mutate mapMigrateStorage, but // migrateStorage's value should always only be associated with the initial state of mapMigrateStorage. diff --git a/plugins/hypervisors/kvm/src/main/java/org/apache/cloudstack/utils/qemu/QemuImg.java b/plugins/hypervisors/kvm/src/main/java/org/apache/cloudstack/utils/qemu/QemuImg.java index e2c03672ccb..3006d256697 100644 --- a/plugins/hypervisors/kvm/src/main/java/org/apache/cloudstack/utils/qemu/QemuImg.java +++ b/plugins/hypervisors/kvm/src/main/java/org/apache/cloudstack/utils/qemu/QemuImg.java @@ -379,8 +379,29 @@ public class QemuImg { } /* Changes the backing file of an image */ - public void rebase() throws QemuImgException { + public void rebase(final QemuImgFile file, final QemuImgFile backingFile, final String backingFileFormat, final boolean secure) throws QemuImgException { + if (backingFile == null) { + throw new QemuImgException("No backing file was passed"); + } + final Script s = new Script(_qemuImgPath, timeout); + s.add("rebase"); + if (! secure) { + s.add("-u"); + } + s.add("-F"); + if (backingFileFormat != null) { + s.add(backingFileFormat); + } else { + s.add(backingFile.getFormat().toString()); + } + s.add("-b"); + s.add(backingFile.getFileName()); + s.add(file.getFileName()); + final String result = s.execute(); + if (result != null) { + throw new QemuImgException(result); + } } /**