Skip to content

Commit 57c61fb

Browse files
authored
Fix direct download https compressed qcow2 template checker (#7932)
This PR fixes an issue on direct download while registering HTTPS compressed files Fixes: #7929
1 parent 89e0a4c commit 57c61fb

File tree

5 files changed

+33
-25
lines changed

5 files changed

+33
-25
lines changed

core/src/main/java/org/apache/cloudstack/direct/download/HttpsDirectTemplateDownloader.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,8 @@ public Long getRemoteFileSize(String url, String format) {
183183
SSLContext context = getSSLContext();
184184
urlConnection.setSSLSocketFactory(context.getSocketFactory());
185185
urlConnection.connect();
186-
return QCOW2Utils.getVirtualSize(urlConnection.getInputStream());
186+
boolean isCompressed = !url.endsWith("qcow2");
187+
return QCOW2Utils.getVirtualSize(urlObj.openStream(), isCompressed);
187188
} catch (IOException e) {
188189
throw new CloudRuntimeException(String.format("Cannot obtain qcow2 virtual size due to: %s", e.getMessage()), e);
189190
}

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCheckUrlCommand.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ public CheckUrlAnswer execute(CheckUrlCommand cmd, LibvirtComputingResource serv
4040
boolean checkResult = DirectDownloadHelper.checkUrlExistence(url);
4141
if (checkResult) {
4242
remoteSize = DirectDownloadHelper.getFileSize(url, cmd.getFormat());
43+
if (remoteSize == null || remoteSize < 0) {
44+
s_logger.error(String.format("Couldn't properly retrieve the remote size of the template on " +
45+
"url %s, obtained size = %s", url, remoteSize));
46+
return new CheckUrlAnswer(false, remoteSize);
47+
}
4348
}
4449
return new CheckUrlAnswer(checkResult, remoteSize);
4550
}

services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/template/DownloadManagerImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ private String postRemoteDownload(String jobId) {
347347
// and as such can be easily read.
348348

349349
try (InputStream inputStream = td.getS3ObjectInputStream();) {
350-
dnld.setTemplatesize(QCOW2Utils.getVirtualSize(inputStream));
350+
dnld.setTemplatesize(QCOW2Utils.getVirtualSize(inputStream, false));
351351
}
352352
catch (IOException e) {
353353
result = "Couldn't read QCOW2 virtual size. Error: " + e.getMessage();

utils/src/main/java/com/cloud/utils/storage/QCOW2Utils.java

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,9 @@
2525
import java.net.MalformedURLException;
2626
import java.net.URL;
2727
import java.nio.ByteBuffer;
28-
import java.nio.charset.Charset;
28+
import java.nio.charset.StandardCharsets;
2929

3030
import org.apache.commons.compress.compressors.CompressorException;
31-
import org.apache.commons.compress.compressors.CompressorInputStream;
3231
import org.apache.commons.compress.compressors.CompressorStreamFactory;
3332
import org.apache.log4j.Logger;
3433

@@ -57,7 +56,10 @@ public static int getVirtualSizeHeaderLocation() {
5756
* @param inputStream The QCOW2 object in stream format.
5857
* @return The virtual size of the QCOW2 object.
5958
*/
60-
public static long getVirtualSize(InputStream inputStream) throws IOException {
59+
public static long getVirtualSize(InputStream inputStream, boolean isCompressed) throws IOException {
60+
if (isCompressed) {
61+
return getVirtualSizeFromInputStream(inputStream);
62+
}
6163
byte[] bytes = new byte[VIRTUALSIZE_HEADER_LENGTH];
6264

6365
if (inputStream.skip(VIRTUALSIZE_HEADER_LOCATION) != VIRTUALSIZE_HEADER_LOCATION) {
@@ -71,20 +73,13 @@ public static long getVirtualSize(InputStream inputStream) throws IOException {
7173
return NumbersUtil.bytesToLong(bytes);
7274
}
7375

74-
public static long getVirtualSize(String urlStr) {
75-
InputStream inputStream = null;
76-
76+
private static long getVirtualSizeFromInputStream(InputStream inputStream) throws IOException {
7777
try {
78-
URL url = new URL(urlStr);
79-
BufferedInputStream bufferedInputStream = new BufferedInputStream(url.openStream());
80-
inputStream = bufferedInputStream;
81-
8278
try {
83-
CompressorInputStream compressorInputStream = new CompressorStreamFactory().createCompressorInputStream(bufferedInputStream);
84-
inputStream = compressorInputStream;
79+
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
80+
inputStream = new CompressorStreamFactory().createCompressorInputStream(bufferedInputStream);
8581
} catch (CompressorException e) {
8682
LOGGER.warn(e.getMessage());
87-
inputStream = bufferedInputStream;
8883
}
8984

9085
byte[] inputBytes = inputStream.readNBytes(VIRTUALSIZE_HEADER_LOCATION + VIRTUALSIZE_HEADER_LENGTH);
@@ -93,7 +88,7 @@ public static long getVirtualSize(String urlStr) {
9388
inputMagicBytes.put(inputBytes, 0, MAGIC_HEADER_LENGTH);
9489

9590
ByteBuffer qcow2MagicBytes = ByteBuffer.allocate(MAGIC_HEADER_LENGTH);
96-
qcow2MagicBytes.put("QFI".getBytes(Charset.forName("UTF-8")));
91+
qcow2MagicBytes.put("QFI".getBytes(StandardCharsets.UTF_8));
9792
qcow2MagicBytes.put((byte)0xfb);
9893

9994
long virtualSize = 0L;
@@ -105,12 +100,6 @@ public static long getVirtualSize(String urlStr) {
105100
}
106101

107102
return virtualSize;
108-
} catch (MalformedURLException e) {
109-
LOGGER.warn("Failed to validate for qcow2, malformed URL: " + urlStr + ", error: " + e.getMessage());
110-
throw new IllegalArgumentException("Invalid URL: " + urlStr);
111-
} catch (IOException e) {
112-
LOGGER.warn("Failed to validate for qcow2, error: " + e.getMessage());
113-
throw new IllegalArgumentException("Failed to connect URL: " + urlStr);
114103
} finally {
115104
if (inputStream != null) {
116105
try {
@@ -121,4 +110,17 @@ public static long getVirtualSize(String urlStr) {
121110
}
122111
}
123112
}
113+
114+
public static long getVirtualSize(String urlStr) {
115+
try {
116+
URL url = new URL(urlStr);
117+
return getVirtualSizeFromInputStream(url.openStream());
118+
} catch (MalformedURLException e) {
119+
LOGGER.warn("Failed to validate for qcow2, malformed URL: " + urlStr + ", error: " + e.getMessage());
120+
throw new IllegalArgumentException("Invalid URL: " + urlStr);
121+
} catch (IOException e) {
122+
LOGGER.warn("Failed to validate for qcow2, error: " + e.getMessage());
123+
throw new IllegalArgumentException("Failed to connect URL: " + urlStr);
124+
}
125+
}
124126
}

utils/src/test/java/com/cloud/utils/storage/QCOW2UtilsTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
import java.io.IOException;
2525
import java.io.InputStream;
2626
import java.nio.ByteBuffer;
27-
import java.nio.charset.Charset;
27+
import java.nio.charset.StandardCharsets;
2828

2929
import org.junit.Before;
3030
import org.junit.Test;
@@ -67,7 +67,7 @@ public void setup() {
6767
ByteBuffer byteBuffer = ByteBuffer.allocate(72);
6868

6969
// Magic
70-
byteBuffer.put("QFI".getBytes(Charset.forName("UTF-8")));
70+
byteBuffer.put("QFI".getBytes(StandardCharsets.UTF_8));
7171
byteBuffer.put((byte)0xfb);
7272

7373
// Version
@@ -116,6 +116,6 @@ public void getVirtualSizeHeaderLocation() {
116116

117117
@Test
118118
public void getVirtualSizeTest() throws IOException {
119-
assertEquals(virtualSize.longValue(), QCOW2Utils.getVirtualSize(inputStream));
119+
assertEquals(virtualSize.longValue(), QCOW2Utils.getVirtualSize(inputStream, false));
120120
}
121121
}

0 commit comments

Comments
 (0)