Set timeout threshold for alibaba ecs identification to avoid hanging.
authorWeisson <hanxiaobupt@bupt.cn>
Fri, 14 Jun 2024 11:30:01 +0000 (19:30 +0800)
committerRichard W.M. Jones <rjones@redhat.com>
Mon, 24 Jun 2024 17:01:34 +0000 (18:01 +0100)
On Alibaba ECS/EBM, virt-what used to run this tricky shell command:
```
( { echo -e "GET /latest/meta-datainstance/instance-type HTTP/1.0\r\nHost: 100.100.100.200\r\n\r" >&3; grep -sq 'ebm' <&3 ; } 3<> /dev/tcp/100.100.100.200/80 ) 2>/dev/null
```
which means the host fetches metadata and identifies its flavor.

However, the remote server '100.100.100.200' is accessible only within
Alibaba Cloud network, which keeps those hosts, not in that condition
mentioned above, hanging until syscall 'connect' timeout and get interrupted
by kernel, or even worse, hanging forever.

This commit set 1 second timeout at most for meta-data fetching process
to avoid that kind of hanging.

Signed-off-by: Weisson <hanxiaobupt@bupt.cn>
tests/alibaba-cloud-arm/sbin/timeout [new file with mode: 0755]
tests/alibaba-cloud-x86/sbin/timeout [new file with mode: 0755]
virt-what.in

diff --git a/tests/alibaba-cloud-arm/sbin/timeout b/tests/alibaba-cloud-arm/sbin/timeout
new file mode 100755 (executable)
index 0000000..b5eae13
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/sh -
+
+if [ $# -ne 0 ]; then
+       exit 0;
+fi
+
+# fake metadata
+echo ecs.xxxxx.large
+
+# fake timeout behavior
+exit 124
diff --git a/tests/alibaba-cloud-x86/sbin/timeout b/tests/alibaba-cloud-x86/sbin/timeout
new file mode 100755 (executable)
index 0000000..b5eae13
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/sh -
+
+if [ $# -ne 0 ]; then
+       exit 0;
+fi
+
+# fake metadata
+echo ecs.xxxxx.large
+
+# fake timeout behavior
+exit 124
index 5ccf49e..7fd6cce 100644 (file)
@@ -115,11 +115,29 @@ arch=$(uname -m | sed -e 's/i.86/i386/' | sed -e 's/arm.*/arm/')
 
 # Check for Alibaba Cloud
 if echo "$dmi" | grep -q 'Manufacturer: Alibaba'; then
-    # Check for Alibaba Cloud ECS Bare Metal (EBM) Instance
-    if [ "x$root" = "x" ] && ( { echo -e "GET /latest/meta-datainstance/instance-type HTTP/1.0\r\nHost: 100.100.100.200\r\n\r" >&3; grep -sq 'ebm' <&3 ; } 3<> /dev/tcp/100.100.100.200/80 ) 2>/dev/null ; then
-        echo "alibaba_cloud-ebm"
+    if $(timeout --version >/dev/null 2>&1); then
+        timeout_cmd_prefix="timeout 1s"
+        timeout_cmp="-eq"
+        timeout_return_value=124
     else
+        timeout_cmd_prefix=""
+        timeout_cmp="-ne"
+        timeout_return_value=0
+    fi
+
+    # Check for Alibaba Cloud ECS Bare Metal (EBM) Instance
+    metadata=$($timeout_cmd_prefix sh -c '( { echo -e "GET /latest/meta-datainstance/instance-type HTTP/1.0\r\nHost: 100.100.100.200\r\n\r" >&3; grep -s 'ebm' <&3 ; } 3<> /dev/tcp/100.100.100.200/80 ) 2>/dev/null')
+    ret_value=$?
+    if [ $ret_value $timeout_cmp $timeout_return_value ]; then
+        # a timeout occurred when fetching metadata, assuming remote host unaccessible
+        # which means it might be a non-cloud environment, or test environment.
         echo "alibaba_cloud"
+    else
+        if [ -z "$metadata" ] ; then
+            echo "alibaba_cloud"
+        else
+            echo "alibaba_cloud-ebm"
+        fi
     fi
 fi