EXSi Import tool : Patch to make it work using VSphere and HTTP/1

arnaudaujon

New Member
Apr 22, 2024
2
0
1
Hi,

I'm currently migrating from a hosted ESXi (OVH private cloud) to a new Proxmox infrastructure. I can't access to the esx nodes directly so I have to go through the vsphere interface that doesn't support HTTP/2.
Because of that, the esxi migration tool doesn't work since this commit : https://git.proxmox.com/?p=pve-esxi...it;h=47e1e13966ca221d8f2fecb3049d3884772151a7
It makes use of the content-length header for a HEAD request that's only available on HTTP/2, it results in this error on my environment :
esxi-folder-fuse[26476]: Error: error when getting file size

I made a quick & dirty patch to make it work, it's clearly badly developed as the tool now download the file 2 times.. but I'm not a Rust developper :/
I guess a better way would be to provide a --http1 flag to switch to this fallback and rework the code a bit to avoid this double download. If someone is willing to do that, that would be great :)

Maybe it can help others here :

Git:
diff --git a/Cargo.toml b/Cargo.toml
index f7444a3..5f9c45f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -14,7 +14,7 @@ homepage = "https://www.proxmox.com"
 anyhow = "1"
 futures = "0.3.28"
 http = "0.2.9"
-hyper = { version = "0.14", features = [ "http1", "http2" ] }
+hyper = { version = "0.14", features = [ "http1" ] }
 libc = "0.2"
 log = "0.4"
 nix = "0.26"
diff --git a/src/esxi.rs b/src/esxi.rs
index 88930b0..ecd1697 100644
--- a/src/esxi.rs
+++ b/src/esxi.rs
@@ -243,13 +243,37 @@ impl EsxiClient {
             return Err(IsDirectory.into());
         }
 
-        headers
+        self.get_file_size_fallback(datacenter, datastore, path).await
+        
+        /*headers
             .get("content-length")
             .ok_or_else(|| format_err!("http response did not include a content-length"))?
             .to_str()
             .context("content-length header is not a number")?
             .parse::<u64>()
             .context("failed to parse content size")
+        */
+    }
+
+    /// Get file size fallback in case there is no HTTP/2 support
+    pub async fn get_file_size_fallback(
+        &self,       
+        datacenter: &str,
+        datastore: &str,
+        path: &str,
+    ) -> Result<u64, Error> {
+
+        let (parts, body) = self.make_request(|| Ok(Request::get(self.file_url(datacenter, datastore, path)))).await?.into_parts();
+ 
+        if !parts.status.is_success() {
+          bail!("http error code {:?}", parts.status);
+        }
+
+        let body_bytes = hyper::body::to_bytes(body).await?;
+        let length :u64 = body_bytes.len() as u64;
+        log::debug!("{:?}", body_bytes);
+        log::debug!("length {:?}", length);
+        Ok(length)
     }
 
     /// Check the existence of an URL.
diff --git a/src/main.rs b/src/main.rs
index 216173d..76652a9 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -286,9 +286,6 @@ async fn main_do() -> Result<(), Error> {
     if args.skip_cert_verification {
         connector.set_verify(openssl::ssl::SslVerifyMode::NONE);
     }
-    connector
-        .set_alpn_protos(b"\x02h2")
-        .context("failed to configure alpn protocols")?;
     let connector = connector.build();
 
     let client = Arc::new(EsxiClient::new(

Cheers,