Skip to content

Commit 7f13beb

Browse files
authored
Check Qcow2 version before using --bitmaps (#10896)
* check version before using --bitmaps * use cloudruntimeexception
1 parent 380884e commit 7f13beb

File tree

2 files changed

+32
-1
lines changed
  • plugins/hypervisors/kvm/src/main/java/org/apache/cloudstack/utils/qemu
  • services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/formatinspector

2 files changed

+32
-1
lines changed

plugins/hypervisors/kvm/src/main/java/org/apache/cloudstack/utils/qemu/QemuImg.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import java.util.Map;
2525
import java.util.regex.Pattern;
2626

27+
import org.apache.cloudstack.storage.formatinspector.Qcow2Inspector;
2728
import org.apache.commons.lang.NotImplementedException;
2829
import org.apache.commons.lang3.StringUtils;
2930
import org.libvirt.LibvirtException;
@@ -53,6 +54,8 @@ public class QemuImg {
5354
public static final long QEMU_2_10 = 2010000;
5455
public static final long QEMU_5_10 = 5010000;
5556

57+
public static final int MIN_BITMAP_VERSION = 3;
58+
5659
/* The qemu-img binary. We expect this to be in $PATH */
5760
public String _qemuImgPath = "qemu-img";
5861
private String cloudQemuImgPath = "cloud-qemu-img";
@@ -466,7 +469,7 @@ public void convert(final QemuImgFile srcFile, final QemuImgFile destFile,
466469
script.add(srcFile.getFileName());
467470
}
468471

469-
if (this.version >= QEMU_5_10 && keepBitmaps) {
472+
if (this.version >= QEMU_5_10 && keepBitmaps && Qcow2Inspector.validateQcow2Version(srcFile.getFileName(), MIN_BITMAP_VERSION)) {
470473
script.add("--bitmaps");
471474
}
472475

services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/formatinspector/Qcow2Inspector.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@
1818
package org.apache.cloudstack.storage.formatinspector;
1919

2020
import com.cloud.utils.NumbersUtil;
21+
import com.cloud.utils.exception.CloudRuntimeException;
2122
import org.apache.commons.lang3.ArrayUtils;
2223
import org.apache.logging.log4j.LogManager;
2324
import org.apache.logging.log4j.Logger;
2425

2526
import java.io.FileInputStream;
2627
import java.io.IOException;
2728
import java.io.InputStream;
29+
import java.math.BigInteger;
2830
import java.util.Arrays;
2931
import java.util.HashMap;
3032
import java.util.Map;
@@ -108,6 +110,32 @@ public static Map<String, byte[]> unravelQcow2Header(InputStream qcow2InputStrea
108110
return result;
109111
}
110112

113+
114+
/**
115+
* Validates if the file has a minimum version.
116+
* @param filePath Path of the file to be validated.
117+
* @param minVersion the minimum version that it should contain.
118+
* @throws RuntimeException If a IOException is thrown.
119+
* @return true if file version is >= minVersion, false otherwise.
120+
*/
121+
public static boolean validateQcow2Version(String filePath, int minVersion) {
122+
try (InputStream inputStream = new FileInputStream(filePath)) {
123+
for (Qcow2HeaderField qcow2Header : Qcow2HeaderField.values()) {
124+
if (qcow2Header != Qcow2HeaderField.VERSION) {
125+
skipHeader(inputStream, qcow2Header, filePath);
126+
continue;
127+
}
128+
129+
byte[] headerValue = readHeader(inputStream, qcow2Header, filePath);
130+
int version = new BigInteger(headerValue).intValue();
131+
return version >= minVersion;
132+
}
133+
} catch (IOException ex) {
134+
throw new CloudRuntimeException(String.format("Unable to validate file [%s] due to: ", filePath), ex);
135+
}
136+
return false;
137+
}
138+
111139
/**
112140
* Skips the field's length in the InputStream.
113141
* @param qcow2InputStream InputStream of the QCOW2 being unraveled.

0 commit comments

Comments
 (0)