Fix: Abort script earlier when no objects to cleanup
[releng/global-jjb.git] / shell / openstack-cleanup-orphaned-ports.sh
old mode 100644 (file)
new mode 100755 (executable)
index e1f8436..65ca372
@@ -14,45 +14,73 @@ echo "---> Orphaned ports"
 # shellcheck disable=SC1090
 source ~/lf-env.sh
 
+lf-activate-venv --python python3 "lftools[openstack]" \
+        python-openstackclient
+
 os_cloud="${OS_CLOUD:-vex}"
 
-# Check if openstack venv was previously created
-if [ -f "/tmp/.os_lf_venv" ]; then
-    os_lf_venv=$(cat "/tmp/.os_lf_venv")
-fi
+set -eu -o pipefail
 
-if [ -d "${os_lf_venv}" ] && [ -f "${os_lf_venv}/bin/openstack" ]; then
-    echo "Re-use existing venv: ${os_lf_venv}"
-    PATH=$os_lf_venv/bin:$PATH
-else
-    lf-activate-venv --python python3 \
-        python-heatclient \
-        python-openstackclient
-fi
+tmpfile=$(mktemp --suffix -openstack-ports.txt)
+cores=$(nproc --all)
+threads=$((3*cores))
+regex_created_at='^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2})Z$'
+
+# Set age for deletion/removal
+age="30 minutes ago"
+cutoff=$(date -d "$age" +%s)
+
+_cleanup()
+{
+    uuid=$1
+    created_at=$(openstack --os-cloud "$os_cloud" port show -f value -c created_at "$uuid")
+
+    if [ "$created_at" == "None" ]; then
+        # This is a valid result for some objects; do not stop processing
+        echo "No value for port creation time; skipping: $uuid"
+
+    elif echo "$created_at" | grep -qP "$regex_created_at"; then
 
-set -eux -o pipefail
-
-mapfile -t os_ports_ts < <(openstack --os-cloud "$os_cloud" port list \
-        -f value \
-        -c ID \
-        -c status \
-        -c created_at \
-        | grep -E DOWN \
-        | awk -F' ' '{print $1 " " $3}')
-
-if [ ${#os_ports_ts[@]} -eq 0 ]; then
-    echo "No orphaned ports found."
-else
-    cutoff=$(date -d "30 minutes ago"  +%s)
-    for port_ts in "${os_ports_ts[@]}"; do
-        created_at_isots="${port_ts#* }"
-        port_uuid="${port_ts% *}"
-        echo "checking port uuid: ${port_uuid} with TS: ${created_at_isots}"
-        created_at_uxts=$(date -d "${created_at_isots}" +"%s")
-        # Clean up ports where created_at > 30 minutes
-        if [[ "$created_at_uxts" -gt "$cutoff" ]]; then
-            echo "Removing orphaned port $port_uuid created_at ts > 30 minutes."
-            openstack --os-cloud "$os_cloud" port delete "$port_uuid"
+        created_at_uxts=$(date -d "$created_at" +"%s")
+
+        # Cleanup objects where created_at is older than specified cutoff time
+        # created_at_uxts is measured against UNIX epoch; lower values are older
+        if [[ "$created_at_uxts" -lt "$cutoff" ]]; then
+            echo "Removing orphaned port $uuid created $created_at_uxts > $age"
+            openstack --os-cloud "$os_cloud" port delete "$uuid"
         fi
-    done
+    else
+        # Don't stop the job, but warn about unexpected value
+        echo "Unknown/unexpected value for created_at: ${created_at}"
+    fi
+}
+
+_rmtemp()
+{
+    if [ -f "$tmpfile" ]; then
+        # Removes temporary file on script exit
+        rm -f "$tmpfile"
+    fi
+}
+
+trap _rmtemp EXIT
+
+# Output the initial list of port UUIDs to a temporary file
+openstack --os-cloud "$os_cloud" port list -f value -c ID -c status \
+    | { grep -e DOWN || true; } | { awk '{print $1}' || true; } > "$tmpfile"
+
+# Count the number to process
+total=$(wc -l "$tmpfile" | awk '{print $1}')
+
+if [ "$total" -eq 0 ]; then
+    echo "No orphaned ports to process."
+    exit 0
 fi
+
+echo "Ports to process: $total; age limit: $cutoff"
+echo "Using $threads parallel processes..."
+
+# Export variables and send to parallel for processing
+export -f _cleanup
+export os_cloud cutoff age
+parallel --progress --retries 3 -j "$threads" _cleanup < "$tmpfile"