Copilot commented on code in PR #12773:
URL: https://github.com/apache/cloudstack/pull/12773#discussion_r2906433893


##########
scripts/vm/hypervisor/kvm/kvmsmpheartbeat.sh:
##########
@@ -0,0 +1,218 @@
+#!/bin/bash
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+help() {
+  printf "Usage: $0
+                -i identifier (ignored for local-only heartbeat)
+                -p path (ignored for local-only heartbeat)
+                -m mount point (local path where heartbeat will be written)
+                -h host (host IP/name to include in heartbeat filename)
+                -r write/read hb log (read-check mode)
+                -c cleanup (trigger emergency reboot)
+                -t interval between read hb log\n"
+  exit 1
+}
+
+#set -x
+NfsSvrIP=
+NfsSvrPath=
+MountPoint=
+HostIP=
+interval=
+rflag=0
+cflag=0
+
+while getopts 'i:p:m:h:t:rc' OPTION
+do
+  case $OPTION in
+  i)
+     NfsSvrIP="$OPTARG"
+     ;; # retained for CLI compatibility but unused for local-only script
+  p)
+     NfsSvrPath="$OPTARG"
+     ;; # retained for CLI compatibility but unused for local-only script
+  m)
+     MountPoint="$OPTARG"
+     ;;
+  h)
+     HostIP="$OPTARG"
+     ;;
+  r)
+     rflag=1
+     ;;
+  t)
+     interval="$OPTARG"
+     ;;
+  c)
+    cflag=1
+     ;;
+  *)
+     help
+     ;;
+  esac
+done
+
+# Match original kvmheartbeat.sh: require NfsSvrIP parameter for CLI 
compatibility
+if [ -z "$NfsSvrIP" ]
+then
+   exit 1
+fi
+
+# For local-only heartbeat we require a mountpoint
+if [ -z "$MountPoint" ]
+then
+   echo "Mount point (-m) is required"
+   help
+fi
+
+# Ensure mount point exists and is writable
+if [ ! -d "$MountPoint" ]; then
+  mkdir -p "$MountPoint" 2>/dev/null
+  if [ $? -ne 0 ]; then
+    echo "Failed to create mount point directory: $MountPoint" >&2
+    exit 1
+  fi
+fi
+
+# Determine a sensible HostIP if not provided
+if [ -z "$HostIP" ]; then
+  # try to get a non-loopback IPv4 address, fallback to hostname
+  ipaddr=$(hostname -I 2>/dev/null | awk '{print $1}')
+  if [ -n "$ipaddr" ]; then
+    HostIP="$ipaddr"
+  else
+    HostIP=$(hostname)
+  fi
+fi
+
+#delete VMs on this mountpoint (best-effort)
+deleteVMs() {
+  local mountPoint=$1
+  vmPids=$(ps aux | grep qemu | grep "$mountPoint" | awk '{print $2}' 2> 
/dev/null)
+  if [ $? -gt 0 ]
+  then
+     return
+  fi
+
+  if [ -z "$vmPids" ]
+  then
+     return
+  fi
+
+  for pid in $vmPids
+  do
+     kill -9 $pid &> /dev/null
+  done
+}
+
+#checking is there the mount point present under $MountPoint?
+mounts=$(cat /proc/mounts | grep "$MountPoint")
+if [ $? -gt 0 ]
+then
+   # mount point not present — we don't remount in local-only script
+   # nothing to do here; keep for compatibility with original flow
+   :
+else
+   # mount exists; if not in read-check mode, consider deleting VMs similar to 
original behavior
+   if [ "$rflag" == "0" ]
+   then
+     deleteVMs $MountPoint
+   fi
+fi
+
+hbFolder="$MountPoint/KVMHA/"
+hbFile="$hbFolder/hb-$HostIP"
+
+write_hbLog() {
+#write the heart beat log
+  stat "$hbFile" &> /dev/null
+  if [ $? -gt 0 ]
+  then
+     # create a new one
+     mkdir -p "$hbFolder" &> /dev/null
+     # touch will be done by atomic write below; ensure folder is writable
+     if [ ! -w "$hbFolder" ]; then
+       printf "Folder not writable: $hbFolder" >&2
+       return 2
+     fi
+  fi
+
+  timestamp=$(date +%s)
+  # Write atomically to avoid partial writes (write to tmp then mv)
+  tmpfile="${hbFile}.$$"
+  printf "%s\n" "$timestamp" > "$tmpfile" 2>/dev/null
+  if [ $? -ne 0 ]; then
+    printf "Failed to write heartbeat to $tmpfile" >&2
+    return 2
+  fi
+  mv -f "$tmpfile" "$hbFile" 2>/dev/null
+  return $?
+}
+
+check_hbLog() {
+  if [ ! -f "$hbFile" ]; then
+    # signal large difference if file missing
+    return 999999
+  fi
+  now=$(date +%s)
+  hb=$(cat "$hbFile" 2>/dev/null)
+  if [ -z "$hb" ]; then
+    return 999998
+  fi
+  diff=`expr $now - $hb 2>/dev/null`
+  if [ $? -ne 0 ]
+  then
+    return 999997
+  fi
+  if [ -z "$interval" ]; then
+    # if no interval provided, consider 0 as success
+    if [ $diff -gt 0 ]; then
+      return $diff
+    else
+      return 0
+    fi
+  fi
+  if [ $diff -gt $interval ]
+  then
+    return $diff
+  fi
+  return 0
+}
+
+if [ "$rflag" == "1" ]
+then
+  check_hbLog
+  diff=$?
+  if [ $diff == 0 ]

Review Comment:
   `return` in bash only supports exit codes 0–255; values like 999999 will 
wrap modulo 256, so `diff=$?` will not contain the intended “seconds ago” value 
and can lead to incorrect DEAD/ALIVE reporting. Consider having `check_hbLog` 
print the computed diff (e.g., via `echo`) and use its return code only as 
success/failure, or store the diff in a global variable and return 0/1.
   ```suggestion
     hb_diff=0
     if [ ! -f "$hbFile" ]; then
       # signal large difference if file missing
       hb_diff=999999
       return 1
     fi
     now=$(date +%s)
     hb=$(cat "$hbFile" 2>/dev/null)
     if [ -z "$hb" ]; then
       hb_diff=999998
       return 1
     fi
     diff=`expr $now - $hb 2>/dev/null`
     if [ $? -ne 0 ]
     then
       hb_diff=999997
       return 1
     fi
     if [ -z "$interval" ]; then
       # if no interval provided, consider 0 as success
       if [ $diff -gt 0 ]; then
         hb_diff=$diff
         return 1
       else
         hb_diff=0
         return 0
       fi
     fi
     if [ $diff -gt $interval ]
     then
       hb_diff=$diff
       return 1
     fi
     hb_diff=0
     return 0
   }
   
   if [ "$rflag" == "1" ]
   then
     check_hbLog
     status=$?
     diff="${hb_diff:-0}"
     if [ $status -eq 0 ]
   ```



##########
scripts/vm/hypervisor/kvm/kvmsmpheartbeat.sh:
##########
@@ -0,0 +1,218 @@
+#!/bin/bash
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+help() {
+  printf "Usage: $0
+                -i identifier (ignored for local-only heartbeat)
+                -p path (ignored for local-only heartbeat)
+                -m mount point (local path where heartbeat will be written)
+                -h host (host IP/name to include in heartbeat filename)
+                -r write/read hb log (read-check mode)
+                -c cleanup (trigger emergency reboot)
+                -t interval between read hb log\n"
+  exit 1
+}
+
+#set -x
+NfsSvrIP=
+NfsSvrPath=
+MountPoint=
+HostIP=
+interval=
+rflag=0
+cflag=0
+
+while getopts 'i:p:m:h:t:rc' OPTION
+do
+  case $OPTION in
+  i)
+     NfsSvrIP="$OPTARG"
+     ;; # retained for CLI compatibility but unused for local-only script
+  p)
+     NfsSvrPath="$OPTARG"
+     ;; # retained for CLI compatibility but unused for local-only script
+  m)
+     MountPoint="$OPTARG"
+     ;;
+  h)
+     HostIP="$OPTARG"
+     ;;
+  r)
+     rflag=1
+     ;;
+  t)
+     interval="$OPTARG"
+     ;;
+  c)
+    cflag=1
+     ;;
+  *)
+     help
+     ;;
+  esac
+done
+
+# Match original kvmheartbeat.sh: require NfsSvrIP parameter for CLI 
compatibility
+if [ -z "$NfsSvrIP" ]
+then
+   exit 1
+fi
+
+# For local-only heartbeat we require a mountpoint
+if [ -z "$MountPoint" ]
+then
+   echo "Mount point (-m) is required"
+   help
+fi
+
+# Ensure mount point exists and is writable
+if [ ! -d "$MountPoint" ]; then
+  mkdir -p "$MountPoint" 2>/dev/null
+  if [ $? -ne 0 ]; then
+    echo "Failed to create mount point directory: $MountPoint" >&2
+    exit 1
+  fi
+fi
+
+# Determine a sensible HostIP if not provided
+if [ -z "$HostIP" ]; then
+  # try to get a non-loopback IPv4 address, fallback to hostname
+  ipaddr=$(hostname -I 2>/dev/null | awk '{print $1}')
+  if [ -n "$ipaddr" ]; then
+    HostIP="$ipaddr"
+  else
+    HostIP=$(hostname)
+  fi
+fi
+
+#delete VMs on this mountpoint (best-effort)
+deleteVMs() {
+  local mountPoint=$1
+  vmPids=$(ps aux | grep qemu | grep "$mountPoint" | awk '{print $2}' 2> 
/dev/null)
+  if [ $? -gt 0 ]
+  then
+     return
+  fi
+
+  if [ -z "$vmPids" ]
+  then
+     return
+  fi
+
+  for pid in $vmPids
+  do
+     kill -9 $pid &> /dev/null
+  done
+}
+
+#checking is there the mount point present under $MountPoint?
+mounts=$(cat /proc/mounts | grep "$MountPoint")
+if [ $? -gt 0 ]
+then
+   # mount point not present — we don't remount in local-only script
+   # nothing to do here; keep for compatibility with original flow
+   :
+else

Review Comment:
   `grep "$MountPoint"` can produce false positives when `$MountPoint` is a 
substring of another mount target (e.g., `/mnt/cloudstack1` matching 
`/mnt/cloudstack10`). This can incorrectly treat the mount as present and 
trigger `deleteVMs`. Consider using a stricter mount check (e.g., matching the 
mount target field exactly or using `findmnt`).



##########
scripts/vm/hypervisor/kvm/kvmsmpheartbeat.sh:
##########
@@ -0,0 +1,218 @@
+#!/bin/bash
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+help() {
+  printf "Usage: $0
+                -i identifier (ignored for local-only heartbeat)
+                -p path (ignored for local-only heartbeat)
+                -m mount point (local path where heartbeat will be written)
+                -h host (host IP/name to include in heartbeat filename)
+                -r write/read hb log (read-check mode)
+                -c cleanup (trigger emergency reboot)
+                -t interval between read hb log\n"
+  exit 1
+}
+
+#set -x
+NfsSvrIP=
+NfsSvrPath=
+MountPoint=
+HostIP=
+interval=
+rflag=0
+cflag=0
+
+while getopts 'i:p:m:h:t:rc' OPTION
+do
+  case $OPTION in
+  i)
+     NfsSvrIP="$OPTARG"
+     ;; # retained for CLI compatibility but unused for local-only script
+  p)
+     NfsSvrPath="$OPTARG"
+     ;; # retained for CLI compatibility but unused for local-only script
+  m)
+     MountPoint="$OPTARG"
+     ;;
+  h)
+     HostIP="$OPTARG"
+     ;;
+  r)
+     rflag=1
+     ;;
+  t)
+     interval="$OPTARG"
+     ;;
+  c)
+    cflag=1
+     ;;
+  *)
+     help
+     ;;
+  esac
+done
+
+# Match original kvmheartbeat.sh: require NfsSvrIP parameter for CLI 
compatibility
+if [ -z "$NfsSvrIP" ]
+then
+   exit 1
+fi
+

Review Comment:
   The help text says `-i` is “ignored for local-only heartbeat”, but the 
script hard-requires it and exits with status 1 without any message. Consider 
either (a) not requiring `-i` for this script, or (b) emitting a clear error 
(and/or calling `help`) explaining why it’s required for compatibility.
   ```suggestion
   
   ```



##########
plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java:
##########
@@ -57,7 +57,7 @@ public class KVMStoragePoolManager {
     private final Map<String, StoragePoolInformation> _storagePools = new 
ConcurrentHashMap<String, StoragePoolInformation>();
     private final Map<String, StorageAdaptor> _storageMapper = new 
HashMap<String, StorageAdaptor>();
 
-    private StorageAdaptor getStorageAdaptor(StoragePoolType type) {
+    public StorageAdaptor getStorageAdaptor(StoragePoolType type) {

Review Comment:
   Changing this method from `private` to `public` expands the exposed API 
surface of `KVMStoragePoolManager`, which can make future refactors harder. If 
external access is required, consider narrowing visibility (package-private) or 
providing a more purpose-driven public method; if it’s only needed for tests, 
consider a test-oriented visibility approach rather than making it broadly 
public.
   ```suggestion
       StorageAdaptor getStorageAdaptor(StoragePoolType type) {
   ```



##########
scripts/vm/hypervisor/kvm/kvmsmpheartbeat.sh:
##########
@@ -0,0 +1,218 @@
+#!/bin/bash
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+help() {
+  printf "Usage: $0
+                -i identifier (ignored for local-only heartbeat)
+                -p path (ignored for local-only heartbeat)
+                -m mount point (local path where heartbeat will be written)
+                -h host (host IP/name to include in heartbeat filename)
+                -r write/read hb log (read-check mode)
+                -c cleanup (trigger emergency reboot)
+                -t interval between read hb log\n"
+  exit 1
+}
+
+#set -x
+NfsSvrIP=
+NfsSvrPath=
+MountPoint=
+HostIP=
+interval=
+rflag=0
+cflag=0
+
+while getopts 'i:p:m:h:t:rc' OPTION
+do
+  case $OPTION in
+  i)
+     NfsSvrIP="$OPTARG"
+     ;; # retained for CLI compatibility but unused for local-only script
+  p)
+     NfsSvrPath="$OPTARG"
+     ;; # retained for CLI compatibility but unused for local-only script
+  m)
+     MountPoint="$OPTARG"
+     ;;
+  h)
+     HostIP="$OPTARG"
+     ;;
+  r)
+     rflag=1
+     ;;
+  t)
+     interval="$OPTARG"
+     ;;
+  c)
+    cflag=1
+     ;;
+  *)
+     help
+     ;;
+  esac
+done
+
+# Match original kvmheartbeat.sh: require NfsSvrIP parameter for CLI 
compatibility
+if [ -z "$NfsSvrIP" ]
+then
+   exit 1
+fi
+
+# For local-only heartbeat we require a mountpoint
+if [ -z "$MountPoint" ]
+then
+   echo "Mount point (-m) is required"
+   help
+fi
+
+# Ensure mount point exists and is writable
+if [ ! -d "$MountPoint" ]; then
+  mkdir -p "$MountPoint" 2>/dev/null
+  if [ $? -ne 0 ]; then
+    echo "Failed to create mount point directory: $MountPoint" >&2
+    exit 1
+  fi
+fi
+
+# Determine a sensible HostIP if not provided
+if [ -z "$HostIP" ]; then
+  # try to get a non-loopback IPv4 address, fallback to hostname
+  ipaddr=$(hostname -I 2>/dev/null | awk '{print $1}')
+  if [ -n "$ipaddr" ]; then
+    HostIP="$ipaddr"
+  else
+    HostIP=$(hostname)
+  fi
+fi
+
+#delete VMs on this mountpoint (best-effort)
+deleteVMs() {
+  local mountPoint=$1
+  vmPids=$(ps aux | grep qemu | grep "$mountPoint" | awk '{print $2}' 2> 
/dev/null)
+  if [ $? -gt 0 ]
+  then
+     return
+  fi
+
+  if [ -z "$vmPids" ]
+  then
+     return
+  fi
+
+  for pid in $vmPids
+  do
+     kill -9 $pid &> /dev/null
+  done
+}
+
+#checking is there the mount point present under $MountPoint?
+mounts=$(cat /proc/mounts | grep "$MountPoint")
+if [ $? -gt 0 ]
+then
+   # mount point not present — we don't remount in local-only script
+   # nothing to do here; keep for compatibility with original flow
+   :
+else
+   # mount exists; if not in read-check mode, consider deleting VMs similar to 
original behavior
+   if [ "$rflag" == "0" ]
+   then
+     deleteVMs $MountPoint
+   fi
+fi
+
+hbFolder="$MountPoint/KVMHA/"
+hbFile="$hbFolder/hb-$HostIP"
+
+write_hbLog() {
+#write the heart beat log
+  stat "$hbFile" &> /dev/null
+  if [ $? -gt 0 ]
+  then
+     # create a new one
+     mkdir -p "$hbFolder" &> /dev/null
+     # touch will be done by atomic write below; ensure folder is writable
+     if [ ! -w "$hbFolder" ]; then
+       printf "Folder not writable: $hbFolder" >&2
+       return 2
+     fi
+  fi
+
+  timestamp=$(date +%s)
+  # Write atomically to avoid partial writes (write to tmp then mv)
+  tmpfile="${hbFile}.$$"
+  printf "%s\n" "$timestamp" > "$tmpfile" 2>/dev/null
+  if [ $? -ne 0 ]; then
+    printf "Failed to write heartbeat to $tmpfile" >&2
+    return 2
+  fi
+  mv -f "$tmpfile" "$hbFile" 2>/dev/null
+  return $?
+}
+
+check_hbLog() {
+  if [ ! -f "$hbFile" ]; then
+    # signal large difference if file missing
+    return 999999
+  fi
+  now=$(date +%s)
+  hb=$(cat "$hbFile" 2>/dev/null)
+  if [ -z "$hb" ]; then
+    return 999998
+  fi
+  diff=`expr $now - $hb 2>/dev/null`
+  if [ $? -ne 0 ]
+  then
+    return 999997
+  fi
+  if [ -z "$interval" ]; then
+    # if no interval provided, consider 0 as success
+    if [ $diff -gt 0 ]; then
+      return $diff
+    else
+      return 0
+    fi
+  fi
+  if [ $diff -gt $interval ]
+  then
+    return $diff
+  fi
+  return 0
+}
+
+if [ "$rflag" == "1" ]
+then
+  check_hbLog
+  diff=$?
+  if [ $diff == 0 ]
+  then
+    echo "=====> ALIVE <====="
+  else
+    echo "=====> Considering host as DEAD because last write on [$hbFile] was 
[$diff] seconds ago, but the max interval is [$interval] <======"
+  fi

Review Comment:
   This is doing a numeric comparison but uses the string operator `==` and 
unquoted `$diff`. Use numeric operators (`-eq`, `-ne`) and quote variables in 
`[` tests (or switch to `[[ ... ]]`) to avoid mis-comparisons or test errors if 
the variable is empty/unset.



##########
scripts/vm/hypervisor/kvm/kvmsmpheartbeat.sh:
##########
@@ -0,0 +1,218 @@
+#!/bin/bash
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+help() {
+  printf "Usage: $0
+                -i identifier (ignored for local-only heartbeat)
+                -p path (ignored for local-only heartbeat)

Review Comment:
   The help text says `-i` is “ignored for local-only heartbeat”, but the 
script hard-requires it and exits with status 1 without any message. Consider 
either (a) not requiring `-i` for this script, or (b) emitting a clear error 
(and/or calling `help`) explaining why it’s required for compatibility.
   ```suggestion
                   -i identifier (required for CLI compatibility; value ignored 
by local-only heartbeat)
                   -p path (required for CLI compatibility; value ignored by 
local-only heartbeat)
   ```



##########
plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/KVMHAMonitor.java:
##########
@@ -34,6 +34,8 @@
 
 public class KVMHAMonitor extends KVMHABase implements Runnable {
 
+    public static final List<StoragePoolType> 
STORAGE_POOL_TYPES_WITH_HA_SUPPORT = List.of(StoragePoolType.NetworkFilesystem, 
StoragePoolType.SharedMountPoint);

Review Comment:
   HA-supported pool types are now defined in multiple places (e.g., also in 
`CloudStackPrimaryDataStoreDriverImpl`), and `LibvirtStoragePool` depends on 
`KVMHAMonitor` just to reuse this constant. Consider centralizing this list in 
a small shared utility/helper in an appropriate common package for the KVM 
plugin (or a single authoritative location) to avoid duplication and reduce 
cross-class coupling.



##########
scripts/vm/hypervisor/kvm/kvmsmpheartbeat.sh:
##########
@@ -0,0 +1,218 @@
+#!/bin/bash
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+help() {
+  printf "Usage: $0
+                -i identifier (ignored for local-only heartbeat)
+                -p path (ignored for local-only heartbeat)
+                -m mount point (local path where heartbeat will be written)
+                -h host (host IP/name to include in heartbeat filename)
+                -r write/read hb log (read-check mode)
+                -c cleanup (trigger emergency reboot)
+                -t interval between read hb log\n"
+  exit 1
+}
+
+#set -x
+NfsSvrIP=
+NfsSvrPath=
+MountPoint=
+HostIP=
+interval=
+rflag=0
+cflag=0
+
+while getopts 'i:p:m:h:t:rc' OPTION
+do
+  case $OPTION in
+  i)
+     NfsSvrIP="$OPTARG"
+     ;; # retained for CLI compatibility but unused for local-only script
+  p)
+     NfsSvrPath="$OPTARG"
+     ;; # retained for CLI compatibility but unused for local-only script
+  m)
+     MountPoint="$OPTARG"
+     ;;
+  h)
+     HostIP="$OPTARG"
+     ;;
+  r)
+     rflag=1
+     ;;
+  t)
+     interval="$OPTARG"
+     ;;
+  c)
+    cflag=1
+     ;;
+  *)
+     help
+     ;;
+  esac
+done
+
+# Match original kvmheartbeat.sh: require NfsSvrIP parameter for CLI 
compatibility
+if [ -z "$NfsSvrIP" ]
+then
+   exit 1
+fi
+
+# For local-only heartbeat we require a mountpoint
+if [ -z "$MountPoint" ]
+then
+   echo "Mount point (-m) is required"
+   help
+fi
+
+# Ensure mount point exists and is writable
+if [ ! -d "$MountPoint" ]; then
+  mkdir -p "$MountPoint" 2>/dev/null
+  if [ $? -ne 0 ]; then
+    echo "Failed to create mount point directory: $MountPoint" >&2
+    exit 1
+  fi
+fi
+
+# Determine a sensible HostIP if not provided
+if [ -z "$HostIP" ]; then
+  # try to get a non-loopback IPv4 address, fallback to hostname
+  ipaddr=$(hostname -I 2>/dev/null | awk '{print $1}')
+  if [ -n "$ipaddr" ]; then
+    HostIP="$ipaddr"
+  else
+    HostIP=$(hostname)
+  fi
+fi
+
+#delete VMs on this mountpoint (best-effort)
+deleteVMs() {
+  local mountPoint=$1
+  vmPids=$(ps aux | grep qemu | grep "$mountPoint" | awk '{print $2}' 2> 
/dev/null)
+  if [ $? -gt 0 ]
+  then
+     return
+  fi

Review Comment:
   `$?` here reflects only the exit status of the last command in the pipeline 
(`awk`), not whether `ps`/`grep` matched anything. As written, this check won’t 
behave as intended and is effectively redundant with the later `-z "$vmPids"` 
guard. Consider removing this `$?` block, or use `set -o pipefail` (with care 
for script-wide impact) or replace the pipeline with a more direct PID lookup 
(e.g., `pgrep`) and check for empty output.
   ```suggestion
   
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to