Check Qcow2 version before using --bitmaps (#10896)

* check version before using --bitmaps

* use cloudruntimeexception
This commit is contained in:
João Jandre 2025-06-13 15:30:46 -03:00 committed by GitHub
parent 380884ed50
commit 7f13beb36a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 32 additions and 1 deletions

View File

@ -24,6 +24,7 @@ import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import org.apache.cloudstack.storage.formatinspector.Qcow2Inspector;
import org.apache.commons.lang.NotImplementedException;
import org.apache.commons.lang3.StringUtils;
import org.libvirt.LibvirtException;
@ -53,6 +54,8 @@ public class QemuImg {
public static final long QEMU_2_10 = 2010000;
public static final long QEMU_5_10 = 5010000;
public static final int MIN_BITMAP_VERSION = 3;
/* The qemu-img binary. We expect this to be in $PATH */
public String _qemuImgPath = "qemu-img";
private String cloudQemuImgPath = "cloud-qemu-img";
@ -466,7 +469,7 @@ public class QemuImg {
script.add(srcFile.getFileName());
}
if (this.version >= QEMU_5_10 && keepBitmaps) {
if (this.version >= QEMU_5_10 && keepBitmaps && Qcow2Inspector.validateQcow2Version(srcFile.getFileName(), MIN_BITMAP_VERSION)) {
script.add("--bitmaps");
}

View File

@ -18,6 +18,7 @@
package org.apache.cloudstack.storage.formatinspector;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -25,6 +26,7 @@ import org.apache.logging.log4j.Logger;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@ -108,6 +110,32 @@ public class Qcow2Inspector {
return result;
}
/**
* Validates if the file has a minimum version.
* @param filePath Path of the file to be validated.
* @param minVersion the minimum version that it should contain.
* @throws RuntimeException If a IOException is thrown.
* @return true if file version is >= minVersion, false otherwise.
*/
public static boolean validateQcow2Version(String filePath, int minVersion) {
try (InputStream inputStream = new FileInputStream(filePath)) {
for (Qcow2HeaderField qcow2Header : Qcow2HeaderField.values()) {
if (qcow2Header != Qcow2HeaderField.VERSION) {
skipHeader(inputStream, qcow2Header, filePath);
continue;
}
byte[] headerValue = readHeader(inputStream, qcow2Header, filePath);
int version = new BigInteger(headerValue).intValue();
return version >= minVersion;
}
} catch (IOException ex) {
throw new CloudRuntimeException(String.format("Unable to validate file [%s] due to: ", filePath), ex);
}
return false;
}
/**
* Skips the field's length in the InputStream.
* @param qcow2InputStream InputStream of the QCOW2 being unraveled.