This is an automated email from the ASF dual-hosted git repository.

weizhou pushed a commit to branch 4.18
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


The following commit(s) were added to refs/heads/4.18 by this push:
     new 57c61fb33cf Fix direct download https compressed qcow2 template 
checker (#7932)
57c61fb33cf is described below

commit 57c61fb33cf0a4587983d8b39b6aadd58a26a9b4
Author: Nicolas Vazquez <[email protected]>
AuthorDate: Fri Sep 1 03:16:03 2023 -0300

    Fix direct download https compressed qcow2 template checker (#7932)
    
    This PR fixes an issue on direct download while registering HTTPS 
compressed files
    Fixes: #7929
---
 .../download/HttpsDirectTemplateDownloader.java    |  3 +-
 .../resource/wrapper/LibvirtCheckUrlCommand.java   |  5 +++
 .../storage/template/DownloadManagerImpl.java      |  2 +-
 .../java/com/cloud/utils/storage/QCOW2Utils.java   | 42 +++++++++++-----------
 .../com/cloud/utils/storage/QCOW2UtilsTest.java    |  6 ++--
 5 files changed, 33 insertions(+), 25 deletions(-)

diff --git 
a/core/src/main/java/org/apache/cloudstack/direct/download/HttpsDirectTemplateDownloader.java
 
b/core/src/main/java/org/apache/cloudstack/direct/download/HttpsDirectTemplateDownloader.java
index 908bf22964b..2035aab2aca 100644
--- 
a/core/src/main/java/org/apache/cloudstack/direct/download/HttpsDirectTemplateDownloader.java
+++ 
b/core/src/main/java/org/apache/cloudstack/direct/download/HttpsDirectTemplateDownloader.java
@@ -183,7 +183,8 @@ public class HttpsDirectTemplateDownloader extends 
DirectTemplateDownloaderImpl
                 SSLContext context = getSSLContext();
                 urlConnection.setSSLSocketFactory(context.getSocketFactory());
                 urlConnection.connect();
-                return 
QCOW2Utils.getVirtualSize(urlConnection.getInputStream());
+                boolean isCompressed = !url.endsWith("qcow2");
+                return QCOW2Utils.getVirtualSize(urlObj.openStream(), 
isCompressed);
             } catch (IOException e) {
                 throw new CloudRuntimeException(String.format("Cannot obtain 
qcow2 virtual size due to: %s", e.getMessage()), e);
             }
diff --git 
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCheckUrlCommand.java
 
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCheckUrlCommand.java
index 939d43086f4..935bc8e113b 100644
--- 
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCheckUrlCommand.java
+++ 
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCheckUrlCommand.java
@@ -40,6 +40,11 @@ public class LibvirtCheckUrlCommand extends 
CommandWrapper<CheckUrlCommand, Chec
         boolean checkResult = DirectDownloadHelper.checkUrlExistence(url);
         if (checkResult) {
             remoteSize = DirectDownloadHelper.getFileSize(url, 
cmd.getFormat());
+            if (remoteSize == null || remoteSize < 0) {
+                s_logger.error(String.format("Couldn't properly retrieve the 
remote size of the template on " +
+                        "url %s, obtained size = %s", url, remoteSize));
+                return new CheckUrlAnswer(false, remoteSize);
+            }
         }
         return new CheckUrlAnswer(checkResult, remoteSize);
     }
diff --git 
a/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/template/DownloadManagerImpl.java
 
b/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/template/DownloadManagerImpl.java
index e06d7da210d..f647b497f58 100644
--- 
a/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/template/DownloadManagerImpl.java
+++ 
b/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/template/DownloadManagerImpl.java
@@ -347,7 +347,7 @@ public class DownloadManagerImpl extends ManagerBase 
implements DownloadManager
             // and as such can be easily read.
 
             try (InputStream inputStream = td.getS3ObjectInputStream();) {
-                dnld.setTemplatesize(QCOW2Utils.getVirtualSize(inputStream));
+                dnld.setTemplatesize(QCOW2Utils.getVirtualSize(inputStream, 
false));
             }
             catch (IOException e) {
                 result = "Couldn't read QCOW2 virtual size. Error: " + 
e.getMessage();
diff --git a/utils/src/main/java/com/cloud/utils/storage/QCOW2Utils.java 
b/utils/src/main/java/com/cloud/utils/storage/QCOW2Utils.java
index afd4fe52e0a..32a54722aae 100644
--- a/utils/src/main/java/com/cloud/utils/storage/QCOW2Utils.java
+++ b/utils/src/main/java/com/cloud/utils/storage/QCOW2Utils.java
@@ -25,10 +25,9 @@ import java.io.InputStream;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.nio.ByteBuffer;
-import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
 
 import org.apache.commons.compress.compressors.CompressorException;
-import org.apache.commons.compress.compressors.CompressorInputStream;
 import org.apache.commons.compress.compressors.CompressorStreamFactory;
 import org.apache.log4j.Logger;
 
@@ -57,7 +56,10 @@ public final class QCOW2Utils {
      * @param inputStream The QCOW2 object in stream format.
      * @return The virtual size of the QCOW2 object.
      */
-    public static long getVirtualSize(InputStream inputStream) throws 
IOException {
+    public static long getVirtualSize(InputStream inputStream, boolean 
isCompressed) throws IOException {
+        if (isCompressed) {
+            return getVirtualSizeFromInputStream(inputStream);
+        }
         byte[] bytes = new byte[VIRTUALSIZE_HEADER_LENGTH];
 
         if (inputStream.skip(VIRTUALSIZE_HEADER_LOCATION) != 
VIRTUALSIZE_HEADER_LOCATION) {
@@ -71,20 +73,13 @@ public final class QCOW2Utils {
         return NumbersUtil.bytesToLong(bytes);
     }
 
-    public static long getVirtualSize(String urlStr) {
-        InputStream inputStream = null;
-
+    private static long getVirtualSizeFromInputStream(InputStream inputStream) 
throws IOException {
         try {
-            URL url = new URL(urlStr);
-            BufferedInputStream bufferedInputStream = new 
BufferedInputStream(url.openStream());
-            inputStream = bufferedInputStream;
-
             try {
-                CompressorInputStream compressorInputStream = new 
CompressorStreamFactory().createCompressorInputStream(bufferedInputStream);
-                inputStream = compressorInputStream;
+                BufferedInputStream bufferedInputStream = new 
BufferedInputStream(inputStream);
+                inputStream = new 
CompressorStreamFactory().createCompressorInputStream(bufferedInputStream);
             } catch (CompressorException e) {
                 LOGGER.warn(e.getMessage());
-                inputStream = bufferedInputStream;
             }
 
             byte[] inputBytes = 
inputStream.readNBytes(VIRTUALSIZE_HEADER_LOCATION + VIRTUALSIZE_HEADER_LENGTH);
@@ -93,7 +88,7 @@ public final class QCOW2Utils {
             inputMagicBytes.put(inputBytes, 0, MAGIC_HEADER_LENGTH);
 
             ByteBuffer qcow2MagicBytes = 
ByteBuffer.allocate(MAGIC_HEADER_LENGTH);
-            qcow2MagicBytes.put("QFI".getBytes(Charset.forName("UTF-8")));
+            qcow2MagicBytes.put("QFI".getBytes(StandardCharsets.UTF_8));
             qcow2MagicBytes.put((byte)0xfb);
 
             long virtualSize = 0L;
@@ -105,12 +100,6 @@ public final class QCOW2Utils {
             }
 
             return virtualSize;
-        } catch (MalformedURLException e) {
-            LOGGER.warn("Failed to validate for qcow2, malformed URL: " + 
urlStr + ", error: " + e.getMessage());
-            throw new IllegalArgumentException("Invalid URL: " + urlStr);
-        }  catch (IOException e) {
-            LOGGER.warn("Failed to validate for qcow2, error: " + 
e.getMessage());
-            throw new IllegalArgumentException("Failed to connect URL: " + 
urlStr);
         } finally {
             if (inputStream != null) {
                 try {
@@ -121,4 +110,17 @@ public final class QCOW2Utils {
             }
         }
     }
+
+    public static long getVirtualSize(String urlStr) {
+        try {
+            URL url = new URL(urlStr);
+            return getVirtualSizeFromInputStream(url.openStream());
+        } catch (MalformedURLException e) {
+            LOGGER.warn("Failed to validate for qcow2, malformed URL: " + 
urlStr + ", error: " + e.getMessage());
+            throw new IllegalArgumentException("Invalid URL: " + urlStr);
+        }  catch (IOException e) {
+            LOGGER.warn("Failed to validate for qcow2, error: " + 
e.getMessage());
+            throw new IllegalArgumentException("Failed to connect URL: " + 
urlStr);
+        }
+    }
 }
diff --git a/utils/src/test/java/com/cloud/utils/storage/QCOW2UtilsTest.java 
b/utils/src/test/java/com/cloud/utils/storage/QCOW2UtilsTest.java
index 92881a63cda..0595b2f67db 100644
--- a/utils/src/test/java/com/cloud/utils/storage/QCOW2UtilsTest.java
+++ b/utils/src/test/java/com/cloud/utils/storage/QCOW2UtilsTest.java
@@ -24,7 +24,7 @@ import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.ByteBuffer;
-import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -67,7 +67,7 @@ public class QCOW2UtilsTest {
         ByteBuffer byteBuffer = ByteBuffer.allocate(72);
 
         // Magic
-        byteBuffer.put("QFI".getBytes(Charset.forName("UTF-8")));
+        byteBuffer.put("QFI".getBytes(StandardCharsets.UTF_8));
         byteBuffer.put((byte)0xfb);
 
         // Version
@@ -116,6 +116,6 @@ public class QCOW2UtilsTest {
 
     @Test
     public void getVirtualSizeTest() throws IOException {
-        assertEquals(virtualSize.longValue(), 
QCOW2Utils.getVirtualSize(inputStream));
+        assertEquals(virtualSize.longValue(), 
QCOW2Utils.getVirtualSize(inputStream, false));
     }
 }

Reply via email to