mirror of
https://github.com/apache/cloudstack.git
synced 2025-11-02 11:52:28 +01:00
kvm: set Backing Format of qcow2 images in vm start and migration (#4656)
In previous cloudstack versions, qcow2 image does not have a backing file format. however, it is required in newer qemu versions, for example qemu 4.2 on ubuntu 20.04. steps to reproduce the issue (1) install cloudstack 4.14 or previous version, and ubuntu 19.04 or 18.04/16.04 LTS. (2) create vms. (3) upgrade to 4.15, upgrade os to ubuntu 20.04 , or install a new server with ubuntu 20.04. (4) migrate vm from old ubuntu version to ubuntu 20.04, failed with exception below ``` 2021-02-04 13:43:07,397 DEBUG [resource.wrapper.LibvirtMigrateCommandWrapper] (agentRequest-Handler-1:null) (logid:93da9385) ExecutionException : org.libvirt.LibvirtException: Requested operation is not valid: format of backing image '/mnt/03b6f487-9eaf-38bf-ad2d-d985423b832f/66990fcc-fd98-4932-9649-989bf6583d59' of image '/mnt/03b6f487-9eaf-38bf-ad2d-d985423b832f/a3dd1f0f-2557-4e07-951c-e4eb7b3f38b2' was not specified in the image metadata (See https://libvirt.org/kbase/backing_chains.html for troubleshooting) ``` (5)stop vm, and start it on ubuntu 20.04 server. failed with exception below ``` 2021-02-04 13:46:29,766 WARN [resource.wrapper.LibvirtStartCommandWrapper] (agentRequest-Handler-5:null) (logid:b54745a7) LibvirtException org.libvirt.LibvirtException: Requested operation is not valid: format of backing image '/mnt/03b6f487-9eaf-38bf-ad2d-d985423b832f/66990fcc-fd98-4932-9649-989bf6583d59' of image '/mnt/03b6f487-9eaf-38bf-ad2d-d985423b832f/a3dd1f0f-2557-4e07-951c-e4eb7b3f38b2' was not specified in the image metadata (See https://libvirt.org/kbase/backing_chains.html for troubleshooting) ``` To make testing easier, step 1 and 2 can be replaced by ``` qemu-img create -f qcow2 -b <backing file> <qcow2 image> ``` so qcow2 image does not have a backing file format.
This commit is contained in:
parent
fd49efa9c1
commit
db1e0f49dc
@ -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<String, String> 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<String, String> 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());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -155,6 +155,14 @@ public final class LibvirtMigrateCommandWrapper extends CommandWrapper<MigrateCo
|
||||
// delete the metadata of vm snapshots before migration
|
||||
vmsnapshots = libvirtComputingResource.cleanVMSnapshotMetadata(dm);
|
||||
|
||||
// Verify Format of backing file
|
||||
for (DiskDef disk : disks) {
|
||||
if (disk.getDeviceType() == DiskDef.DeviceType.DISK
|
||||
&& disk.getDiskFormatType() == DiskDef.DiskFmtType.QCOW2) {
|
||||
libvirtComputingResource.setBackingFileFormat(disk.getDiskPath());
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, MigrateCommand.MigrateDiskInfo> 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.
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user