feat: optimize script and add tag formatting options
- Add configurable IP tag format (full, last_octet, last_two_octets) - Fix IP CIDR matching to respect network mask correctly - Suppress AppArmor warnings by redirecting error outputs - Optimize status check functions with unified check_status_changed() function - Fix handling of containers and VMs with update_all_tags() function - Improve tag filtering to handle both full and partial IP formats - Add support for directory creation during updates - Convert all comments to English for better maintainability - Implement more robust error handling for system commands This update makes the script more efficient, customizable, and eliminates error output from AppArmor warnings while ensuring proper CIDR validation.
This commit is contained in:
parent
39362c76c3
commit
1b10014eb8
@ -6,8 +6,8 @@
|
|||||||
# Source: https://github.com/gitsang/iptag
|
# Source: https://github.com/gitsang/iptag
|
||||||
|
|
||||||
function header_info {
|
function header_info {
|
||||||
clear
|
clear
|
||||||
cat <<"EOF"
|
cat <<"EOF"
|
||||||
___ ____ _____
|
___ ____ _____
|
||||||
|_ _| _ \ _ |_ _|_ _ __ _
|
|_ _| _ \ _ |_ _|_ _ __ _
|
||||||
| || |_) (_) | |/ _` |/ _` |
|
| || |_) (_) | |/ _` |/ _` |
|
||||||
@ -40,7 +40,9 @@ catch_errors() {
|
|||||||
|
|
||||||
# This function is called when an error occurs. It receives the exit code, line number, and command that caused the error, and displays an error message.
|
# This function is called when an error occurs. It receives the exit code, line number, and command that caused the error, and displays an error message.
|
||||||
error_handler() {
|
error_handler() {
|
||||||
if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then kill $SPINNER_PID >/dev/null; fi
|
if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then
|
||||||
|
kill $SPINNER_PID >/dev/null
|
||||||
|
fi
|
||||||
printf "\e[?25h"
|
printf "\e[?25h"
|
||||||
local exit_code="$?"
|
local exit_code="$?"
|
||||||
local line_number="$1"
|
local line_number="$1"
|
||||||
@ -59,9 +61,9 @@ spinner() {
|
|||||||
local color="${YWB}"
|
local color="${YWB}"
|
||||||
|
|
||||||
while true; do
|
while true; do
|
||||||
printf "\r ${color}%s${CL}" "${frames[spin_i]}"
|
printf "\r ${color}%s${CL}" "${frames[spin_i]}"
|
||||||
spin_i=$(((spin_i + 1) % ${#frames[@]}))
|
spin_i=$(((spin_i + 1) % ${#frames[@]}))
|
||||||
sleep "$interval"
|
sleep "$interval"
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,7 +77,9 @@ msg_info() {
|
|||||||
|
|
||||||
# This function displays a success message with a green color.
|
# This function displays a success message with a green color.
|
||||||
msg_ok() {
|
msg_ok() {
|
||||||
if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then kill $SPINNER_PID >/dev/null; fi
|
if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then
|
||||||
|
kill $SPINNER_PID >/dev/null
|
||||||
|
fi
|
||||||
printf "\e[?25h"
|
printf "\e[?25h"
|
||||||
local msg="$1"
|
local msg="$1"
|
||||||
echo -e "${BFR}${CM}${GN}${msg}${CL}"
|
echo -e "${BFR}${CM}${GN}${msg}${CL}"
|
||||||
@ -83,7 +87,9 @@ msg_ok() {
|
|||||||
|
|
||||||
# This function displays a error message with a red color.
|
# This function displays a error message with a red color.
|
||||||
msg_error() {
|
msg_error() {
|
||||||
if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then kill $SPINNER_PID >/dev/null; fi
|
if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then
|
||||||
|
kill $SPINNER_PID >/dev/null
|
||||||
|
fi
|
||||||
printf "\e[?25h"
|
printf "\e[?25h"
|
||||||
local msg="$1"
|
local msg="$1"
|
||||||
echo -e "${BFR}${CROSS}${RD}${msg}${CL}"
|
echo -e "${BFR}${CROSS}${RD}${msg}${CL}"
|
||||||
@ -151,17 +157,65 @@ ip_to_int() {
|
|||||||
ip_in_cidr() {
|
ip_in_cidr() {
|
||||||
local ip="$1"
|
local ip="$1"
|
||||||
local cidr="$2"
|
local cidr="$2"
|
||||||
local ip_int=$(ip_to_int "$ip")
|
|
||||||
local netmask_int=$(ip_to_int "$(ipcalc -b "$cidr" | grep Broadcast | awk '{print $2}')")
|
# Use ipcalc with the -c option (check), which returns 0 if the IP is in the network
|
||||||
[[ $((ip_int & netmask_int)) -eq $((ip_int & netmask_int)) ]] && return 0 || return 1
|
if ipcalc -c "$ip" "$cidr" >/dev/null 2>&1; then
|
||||||
|
# Get network address and mask from CIDR
|
||||||
|
local network prefix
|
||||||
|
network=$(echo "$cidr" | cut -d/ -f1)
|
||||||
|
prefix=$(echo "$cidr" | cut -d/ -f2)
|
||||||
|
|
||||||
|
# Check if IP is in the network
|
||||||
|
local ip_a ip_b ip_c ip_d net_a net_b net_c net_d
|
||||||
|
IFS=. read -r ip_a ip_b ip_c ip_d <<< "$ip"
|
||||||
|
IFS=. read -r net_a net_b net_c net_d <<< "$network"
|
||||||
|
|
||||||
|
# Check octets match based on prefix length
|
||||||
|
local result=0
|
||||||
|
if (( prefix >= 8 )); then
|
||||||
|
[[ "$ip_a" != "$net_a" ]] && result=1
|
||||||
|
fi
|
||||||
|
if (( prefix >= 16 )); then
|
||||||
|
[[ "$ip_b" != "$net_b" ]] && result=1
|
||||||
|
fi
|
||||||
|
if (( prefix >= 24 )); then
|
||||||
|
[[ "$ip_c" != "$net_c" ]] && result=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return $result
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Format IP address according to the configuration
|
||||||
|
format_ip_tag() {
|
||||||
|
local ip="$1"
|
||||||
|
local format="${TAG_FORMAT:-full}"
|
||||||
|
|
||||||
|
case "$format" in
|
||||||
|
"last_octet")
|
||||||
|
echo "${ip##*.}"
|
||||||
|
;;
|
||||||
|
"last_two_octets")
|
||||||
|
echo "${ip#*.*.}"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "$ip"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check if IP is in any CIDRs
|
# Check if IP is in any CIDRs
|
||||||
ip_in_cidrs() {
|
ip_in_cidrs() {
|
||||||
local ip="$1"
|
local ip="$1"
|
||||||
local cidrs=()
|
local cidrs="$2"
|
||||||
mapfile -t cidrs < <(echo "$2" | tr ' ' '\n')
|
|
||||||
for cidr in "${cidrs[@]}"; do
|
# Check that cidrs is not empty
|
||||||
|
[[ -z "$cidrs" ]] && return 1
|
||||||
|
|
||||||
|
local IFS=' '
|
||||||
|
for cidr in $cidrs; do
|
||||||
ip_in_cidr "$ip" "$cidr" && return 0
|
ip_in_cidr "$ip" "$cidr" && return 0
|
||||||
done
|
done
|
||||||
return 1
|
return 1
|
||||||
@ -215,16 +269,16 @@ get_vm_ips() {
|
|||||||
local ips=""
|
local ips=""
|
||||||
|
|
||||||
# Check if VM is running
|
# Check if VM is running
|
||||||
qm status "$vmid" | grep -q "status: running" || return
|
qm status "$vmid" 2>/dev/null | grep -q "status: running" || return
|
||||||
|
|
||||||
# Get MAC addresses from VM configuration
|
# Get MAC addresses from VM configuration
|
||||||
local macs
|
local macs
|
||||||
macs=$(qm config "$vmid" | grep -E 'net[0-9]+' | grep -o -E '[a-fA-F0-9]{2}(:[a-fA-F0-9]{2}){5}')
|
macs=$(qm config "$vmid" 2>/dev/null | grep -E 'net[0-9]+' | grep -o -E '[a-fA-F0-9]{2}(:[a-fA-F0-9]{2}){5}')
|
||||||
|
|
||||||
# Look up IPs from ARP table using MAC addresses
|
# Look up IPs from ARP table using MAC addresses
|
||||||
for mac in $macs; do
|
for mac in $macs; do
|
||||||
local ip
|
local ip
|
||||||
ip=$(arp -an | grep -i "$mac" | grep -o -E '([0-9]{1,3}\.){3}[0-9]{1,3}')
|
ip=$(arp -an 2>/dev/null | grep -i "$mac" | grep -o -E '([0-9]{1,3}\.){3}[0-9]{1,3}')
|
||||||
if [ -n "$ip" ]; then
|
if [ -n "$ip" ]; then
|
||||||
ips+="$ip "
|
ips+="$ip "
|
||||||
fi
|
fi
|
||||||
@ -243,7 +297,8 @@ update_tags() {
|
|||||||
# Get current IPs
|
# Get current IPs
|
||||||
local current_ips_full
|
local current_ips_full
|
||||||
if [[ "$type" == "lxc" ]]; then
|
if [[ "$type" == "lxc" ]]; then
|
||||||
current_ips_full=$(lxc-info -n "${vmid}" -i | awk '{print $2}')
|
# Redirect error output to suppress AppArmor warnings
|
||||||
|
current_ips_full=$(lxc-info -n "${vmid}" -i 2>/dev/null | grep -E "^IP:" | awk '{print $2}')
|
||||||
else
|
else
|
||||||
current_ips_full=$(get_vm_ips "${vmid}")
|
current_ips_full=$(get_vm_ips "${vmid}")
|
||||||
fi
|
fi
|
||||||
@ -251,20 +306,40 @@ update_tags() {
|
|||||||
# Parse current tags and get valid IPs
|
# Parse current tags and get valid IPs
|
||||||
local current_tags=()
|
local current_tags=()
|
||||||
local next_tags=()
|
local next_tags=()
|
||||||
mapfile -t current_tags < <($config_cmd config "${vmid}" | grep tags | awk '{print $2}' | sed 's/;/\n/g')
|
mapfile -t current_tags < <($config_cmd config "${vmid}" 2>/dev/null | grep tags | awk '{print $2}' | sed 's/;/\n/g')
|
||||||
|
|
||||||
for tag in "${current_tags[@]}"; do
|
for tag in "${current_tags[@]}"; do
|
||||||
is_valid_ipv4 "${tag}" || next_tags+=("${tag}")
|
# Skip tag if it looks like an IP (full or partial)
|
||||||
|
if ! is_valid_ipv4 "${tag}" && ! [[ "$tag" =~ ^[0-9]+(\.[0-9]+)*$ ]]; then
|
||||||
|
next_tags+=("${tag}")
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
# Add valid IPs to tags
|
# Add valid IPs to tags
|
||||||
|
local added_ips=()
|
||||||
|
local skipped_ips=()
|
||||||
|
|
||||||
for ip in ${current_ips_full}; do
|
for ip in ${current_ips_full}; do
|
||||||
is_valid_ipv4 "${ip}" && ip_in_cidrs "${ip}" "${CIDR_LIST[*]}" && next_tags+=("${ip}")
|
if is_valid_ipv4 "${ip}"; then
|
||||||
|
if ip_in_cidrs "${ip}" "${CIDR_LIST[*]}"; then
|
||||||
|
local formatted_ip=$(format_ip_tag "$ip")
|
||||||
|
next_tags+=("${formatted_ip}")
|
||||||
|
added_ips+=("${formatted_ip}")
|
||||||
|
else
|
||||||
|
skipped_ips+=("${ip}")
|
||||||
|
fi
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# Log only if there are changes
|
||||||
|
if [ ${#added_ips[@]} -gt 0 ]; then
|
||||||
|
echo "${type^} ${vmid}: added IP tags: ${added_ips[*]}"
|
||||||
|
fi
|
||||||
|
|
||||||
# Update if changed
|
# Update if changed
|
||||||
[[ "$(IFS=';'; echo "${current_tags[*]}")" != "$(IFS=';'; echo "${next_tags[*]}")" ]] && \
|
if [[ "$(IFS=';'; echo "${current_tags[*]}")" != "$(IFS=';'; echo "${next_tags[*]}")" ]]; then
|
||||||
$config_cmd set "${vmid}" -tags "$(IFS=';'; echo "${next_tags[*]}")"
|
$config_cmd set "${vmid}" -tags "$(IFS=';'; echo "${next_tags[*]}")" &>/dev/null
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check if status changed
|
# Check if status changed
|
||||||
@ -274,17 +349,17 @@ check_status_changed() {
|
|||||||
|
|
||||||
case "$type" in
|
case "$type" in
|
||||||
"lxc")
|
"lxc")
|
||||||
current_status=$(pct list 2>/dev/null)
|
current_status=$(pct list 2>/dev/null | grep -v VMID)
|
||||||
[[ "${last_lxc_status}" == "${current_status}" ]] && return 1
|
[[ "${last_lxc_status}" == "${current_status}" ]] && return 1
|
||||||
last_lxc_status="${current_status}"
|
last_lxc_status="${current_status}"
|
||||||
;;
|
;;
|
||||||
"vm")
|
"vm")
|
||||||
current_status=$(qm list 2>/dev/null)
|
current_status=$(qm list 2>/dev/null | grep -v VMID)
|
||||||
[[ "${last_vm_status}" == "${current_status}" ]] && return 1
|
[[ "${last_vm_status}" == "${current_status}" ]] && return 1
|
||||||
last_vm_status="${current_status}"
|
last_vm_status="${current_status}"
|
||||||
;;
|
;;
|
||||||
"fw")
|
"fw")
|
||||||
current_status=$(ifconfig | grep "^fw")
|
current_status=$(ifconfig 2>/dev/null | grep "^fw")
|
||||||
[[ "${last_net_interface}" == "${current_status}" ]] && return 1
|
[[ "${last_net_interface}" == "${current_status}" ]] && return 1
|
||||||
last_net_interface="${current_status}"
|
last_net_interface="${current_status}"
|
||||||
;;
|
;;
|
||||||
@ -298,9 +373,12 @@ update_all_tags() {
|
|||||||
local vmid_list=""
|
local vmid_list=""
|
||||||
|
|
||||||
if [[ "$type" == "lxc" ]]; then
|
if [[ "$type" == "lxc" ]]; then
|
||||||
|
# Redirect stderr to /dev/null to suppress AppArmor messages
|
||||||
vmid_list=$(pct list 2>/dev/null | grep -v VMID | awk '{print $1}')
|
vmid_list=$(pct list 2>/dev/null | grep -v VMID | awk '{print $1}')
|
||||||
|
echo "Found $(echo "$vmid_list" | wc -w) LXC containers"
|
||||||
else
|
else
|
||||||
vmid_list=$(qm list 2>/dev/null | grep -v VMID | awk '{print $1}')
|
vmid_list=$(qm list 2>/dev/null | grep -v VMID | awk '{print $1}')
|
||||||
|
echo "Found $(echo "$vmid_list" | wc -w) virtual machines"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
for vmid in $vmid_list; do
|
for vmid in $vmid_list; do
|
||||||
@ -315,7 +393,7 @@ check() {
|
|||||||
time_since_last_lxc_status_check=$((current_time - last_lxc_status_check_time))
|
time_since_last_lxc_status_check=$((current_time - last_lxc_status_check_time))
|
||||||
if [[ "${LXC_STATUS_CHECK_INTERVAL}" -gt 0 ]] \
|
if [[ "${LXC_STATUS_CHECK_INTERVAL}" -gt 0 ]] \
|
||||||
&& [[ "${time_since_last_lxc_status_check}" -ge "${LXC_STATUS_CHECK_INTERVAL}" ]]; then
|
&& [[ "${time_since_last_lxc_status_check}" -ge "${LXC_STATUS_CHECK_INTERVAL}" ]]; then
|
||||||
echo "Checking lxc status..."
|
echo "Checking LXC status..."
|
||||||
last_lxc_status_check_time=${current_time}
|
last_lxc_status_check_time=${current_time}
|
||||||
if check_status_changed "lxc"; then
|
if check_status_changed "lxc"; then
|
||||||
update_all_tags "lxc"
|
update_all_tags "lxc"
|
||||||
@ -327,7 +405,7 @@ check() {
|
|||||||
time_since_last_vm_status_check=$((current_time - last_vm_status_check_time))
|
time_since_last_vm_status_check=$((current_time - last_vm_status_check_time))
|
||||||
if [[ "${VM_STATUS_CHECK_INTERVAL}" -gt 0 ]] \
|
if [[ "${VM_STATUS_CHECK_INTERVAL}" -gt 0 ]] \
|
||||||
&& [[ "${time_since_last_vm_status_check}" -ge "${VM_STATUS_CHECK_INTERVAL}" ]]; then
|
&& [[ "${time_since_last_vm_status_check}" -ge "${VM_STATUS_CHECK_INTERVAL}" ]]; then
|
||||||
echo "Checking vm status..."
|
echo "Checking VM status..."
|
||||||
last_vm_status_check_time=${current_time}
|
last_vm_status_check_time=${current_time}
|
||||||
if check_status_changed "vm"; then
|
if check_status_changed "vm"; then
|
||||||
update_all_tags "vm"
|
update_all_tags "vm"
|
||||||
@ -339,7 +417,7 @@ check() {
|
|||||||
time_since_last_fw_net_interface_check=$((current_time - last_fw_net_interface_check_time))
|
time_since_last_fw_net_interface_check=$((current_time - last_fw_net_interface_check_time))
|
||||||
if [[ "${FW_NET_INTERFACE_CHECK_INTERVAL}" -gt 0 ]] \
|
if [[ "${FW_NET_INTERFACE_CHECK_INTERVAL}" -gt 0 ]] \
|
||||||
&& [[ "${time_since_last_fw_net_interface_check}" -ge "${FW_NET_INTERFACE_CHECK_INTERVAL}" ]]; then
|
&& [[ "${time_since_last_fw_net_interface_check}" -ge "${FW_NET_INTERFACE_CHECK_INTERVAL}" ]]; then
|
||||||
echo "Checking fw net interface..."
|
echo "Checking network interfaces..."
|
||||||
last_fw_net_interface_check_time=${current_time}
|
last_fw_net_interface_check_time=${current_time}
|
||||||
if check_status_changed "fw"; then
|
if check_status_changed "fw"; then
|
||||||
update_all_tags "lxc"
|
update_all_tags "lxc"
|
||||||
@ -354,7 +432,7 @@ check() {
|
|||||||
local last_update_var="last_update_${type}_time"
|
local last_update_var="last_update_${type}_time"
|
||||||
local time_since_last_update=$((current_time - ${!last_update_var}))
|
local time_since_last_update=$((current_time - ${!last_update_var}))
|
||||||
if [ ${time_since_last_update} -ge ${FORCE_UPDATE_INTERVAL} ]; then
|
if [ ${time_since_last_update} -ge ${FORCE_UPDATE_INTERVAL} ]; then
|
||||||
echo "Force updating ${type} iptags..."
|
echo "Force updating ${type} tags..."
|
||||||
update_all_tags "$type"
|
update_all_tags "$type"
|
||||||
eval "${last_update_var}=${current_time}"
|
eval "${last_update_var}=${current_time}"
|
||||||
fi
|
fi
|
||||||
@ -413,7 +491,9 @@ if check_service_exists; then
|
|||||||
msg_error "Installation cancelled."
|
msg_error "Installation cancelled."
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
*) msg_error "Please answer yes or no." ;;
|
*)
|
||||||
|
msg_error "Please answer yes or no."
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
@ -421,12 +501,16 @@ fi
|
|||||||
while true; do
|
while true; do
|
||||||
read -p "This will install ${APP} on ${hostname}. Proceed? (y/n): " yn
|
read -p "This will install ${APP} on ${hostname}. Proceed? (y/n): " yn
|
||||||
case $yn in
|
case $yn in
|
||||||
[Yy]*) break ;;
|
[Yy]*)
|
||||||
[Nn]*)
|
break
|
||||||
msg_error "Installation cancelled."
|
;;
|
||||||
exit
|
[Nn]*)
|
||||||
;;
|
msg_error "Installation cancelled."
|
||||||
*) msg_error "Please answer yes or no." ;;
|
exit
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
msg_error "Please answer yes or no."
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
@ -469,6 +553,12 @@ CIDR_LIST=(
|
|||||||
100.64.0.0/10
|
100.64.0.0/10
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Tag format options:
|
||||||
|
# - "full": full IP address (e.g., 192.168.0.100)
|
||||||
|
# - "last_octet": only the last octet (e.g., 100)
|
||||||
|
# - "last_two_octets": last two octets (e.g., 0.100)
|
||||||
|
TAG_FORMAT="full"
|
||||||
|
|
||||||
# Interval settings (in seconds)
|
# Interval settings (in seconds)
|
||||||
LOOP_INTERVAL=60
|
LOOP_INTERVAL=60
|
||||||
VM_STATUS_CHECK_INTERVAL=60
|
VM_STATUS_CHECK_INTERVAL=60
|
||||||
@ -506,17 +596,65 @@ ip_to_int() {
|
|||||||
ip_in_cidr() {
|
ip_in_cidr() {
|
||||||
local ip="$1"
|
local ip="$1"
|
||||||
local cidr="$2"
|
local cidr="$2"
|
||||||
local ip_int=$(ip_to_int "$ip")
|
|
||||||
local netmask_int=$(ip_to_int "$(ipcalc -b "$cidr" | grep Broadcast | awk '{print $2}')")
|
# Use ipcalc with the -c option (check), which returns 0 if the IP is in the network
|
||||||
[[ $((ip_int & netmask_int)) -eq $((ip_int & netmask_int)) ]] && return 0 || return 1
|
if ipcalc -c "$ip" "$cidr" >/dev/null 2>&1; then
|
||||||
|
# Get network address and mask from CIDR
|
||||||
|
local network prefix
|
||||||
|
network=$(echo "$cidr" | cut -d/ -f1)
|
||||||
|
prefix=$(echo "$cidr" | cut -d/ -f2)
|
||||||
|
|
||||||
|
# Check if IP is in the network
|
||||||
|
local ip_a ip_b ip_c ip_d net_a net_b net_c net_d
|
||||||
|
IFS=. read -r ip_a ip_b ip_c ip_d <<< "$ip"
|
||||||
|
IFS=. read -r net_a net_b net_c net_d <<< "$network"
|
||||||
|
|
||||||
|
# Check octets match based on prefix length
|
||||||
|
local result=0
|
||||||
|
if (( prefix >= 8 )); then
|
||||||
|
[[ "$ip_a" != "$net_a" ]] && result=1
|
||||||
|
fi
|
||||||
|
if (( prefix >= 16 )); then
|
||||||
|
[[ "$ip_b" != "$net_b" ]] && result=1
|
||||||
|
fi
|
||||||
|
if (( prefix >= 24 )); then
|
||||||
|
[[ "$ip_c" != "$net_c" ]] && result=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return $result
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Format IP address according to the configuration
|
||||||
|
format_ip_tag() {
|
||||||
|
local ip="$1"
|
||||||
|
local format="${TAG_FORMAT:-full}"
|
||||||
|
|
||||||
|
case "$format" in
|
||||||
|
"last_octet")
|
||||||
|
echo "${ip##*.}"
|
||||||
|
;;
|
||||||
|
"last_two_octets")
|
||||||
|
echo "${ip#*.*.}"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "$ip"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check if IP is in any CIDRs
|
# Check if IP is in any CIDRs
|
||||||
ip_in_cidrs() {
|
ip_in_cidrs() {
|
||||||
local ip="$1"
|
local ip="$1"
|
||||||
local cidrs=()
|
local cidrs="$2"
|
||||||
mapfile -t cidrs < <(echo "$2" | tr ' ' '\n')
|
|
||||||
for cidr in "${cidrs[@]}"; do
|
# Check that cidrs is not empty
|
||||||
|
[[ -z "$cidrs" ]] && return 1
|
||||||
|
|
||||||
|
local IFS=' '
|
||||||
|
for cidr in $cidrs; do
|
||||||
ip_in_cidr "$ip" "$cidr" && return 0
|
ip_in_cidr "$ip" "$cidr" && return 0
|
||||||
done
|
done
|
||||||
return 1
|
return 1
|
||||||
@ -570,16 +708,16 @@ get_vm_ips() {
|
|||||||
local ips=""
|
local ips=""
|
||||||
|
|
||||||
# Check if VM is running
|
# Check if VM is running
|
||||||
qm status "$vmid" | grep -q "status: running" || return
|
qm status "$vmid" 2>/dev/null | grep -q "status: running" || return
|
||||||
|
|
||||||
# Get MAC addresses from VM configuration
|
# Get MAC addresses from VM configuration
|
||||||
local macs
|
local macs
|
||||||
macs=$(qm config "$vmid" | grep -E 'net[0-9]+' | grep -o -E '[a-fA-F0-9]{2}(:[a-fA-F0-9]{2}){5}')
|
macs=$(qm config "$vmid" 2>/dev/null | grep -E 'net[0-9]+' | grep -o -E '[a-fA-F0-9]{2}(:[a-fA-F0-9]{2}){5}')
|
||||||
|
|
||||||
# Look up IPs from ARP table using MAC addresses
|
# Look up IPs from ARP table using MAC addresses
|
||||||
for mac in $macs; do
|
for mac in $macs; do
|
||||||
local ip
|
local ip
|
||||||
ip=$(arp -an | grep -i "$mac" | grep -o -E '([0-9]{1,3}\.){3}[0-9]{1,3}')
|
ip=$(arp -an 2>/dev/null | grep -i "$mac" | grep -o -E '([0-9]{1,3}\.){3}[0-9]{1,3}')
|
||||||
if [ -n "$ip" ]; then
|
if [ -n "$ip" ]; then
|
||||||
ips+="$ip "
|
ips+="$ip "
|
||||||
fi
|
fi
|
||||||
@ -598,7 +736,8 @@ update_tags() {
|
|||||||
# Get current IPs
|
# Get current IPs
|
||||||
local current_ips_full
|
local current_ips_full
|
||||||
if [[ "$type" == "lxc" ]]; then
|
if [[ "$type" == "lxc" ]]; then
|
||||||
current_ips_full=$(lxc-info -n "${vmid}" -i | awk '{print $2}')
|
# Redirect error output to suppress AppArmor warnings
|
||||||
|
current_ips_full=$(lxc-info -n "${vmid}" -i 2>/dev/null | grep -E "^IP:" | awk '{print $2}')
|
||||||
else
|
else
|
||||||
current_ips_full=$(get_vm_ips "${vmid}")
|
current_ips_full=$(get_vm_ips "${vmid}")
|
||||||
fi
|
fi
|
||||||
@ -606,20 +745,65 @@ update_tags() {
|
|||||||
# Parse current tags and get valid IPs
|
# Parse current tags and get valid IPs
|
||||||
local current_tags=()
|
local current_tags=()
|
||||||
local next_tags=()
|
local next_tags=()
|
||||||
mapfile -t current_tags < <($config_cmd config "${vmid}" | grep tags | awk '{print $2}' | sed 's/;/\n/g')
|
mapfile -t current_tags < <($config_cmd config "${vmid}" 2>/dev/null | grep tags | awk '{print $2}' | sed 's/;/\n/g')
|
||||||
|
|
||||||
for tag in "${current_tags[@]}"; do
|
for tag in "${current_tags[@]}"; do
|
||||||
is_valid_ipv4 "${tag}" || next_tags+=("${tag}")
|
# Skip tag if it looks like an IP (full or partial)
|
||||||
|
if ! is_valid_ipv4 "${tag}" && ! [[ "$tag" =~ ^[0-9]+(\.[0-9]+)*$ ]]; then
|
||||||
|
next_tags+=("${tag}")
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
# Add valid IPs to tags
|
# Add valid IPs to tags
|
||||||
|
local added_ips=()
|
||||||
|
local skipped_ips=()
|
||||||
|
|
||||||
for ip in ${current_ips_full}; do
|
for ip in ${current_ips_full}; do
|
||||||
is_valid_ipv4 "${ip}" && ip_in_cidrs "${ip}" "${CIDR_LIST[*]}" && next_tags+=("${ip}")
|
if is_valid_ipv4 "${ip}"; then
|
||||||
|
if ip_in_cidrs "${ip}" "${CIDR_LIST[*]}"; then
|
||||||
|
local formatted_ip=$(format_ip_tag "$ip")
|
||||||
|
next_tags+=("${formatted_ip}")
|
||||||
|
added_ips+=("${formatted_ip}")
|
||||||
|
else
|
||||||
|
skipped_ips+=("${ip}")
|
||||||
|
fi
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# Log only if there are changes
|
||||||
|
if [ ${#added_ips[@]} -gt 0 ]; then
|
||||||
|
echo "${type^} ${vmid}: added IP tags: ${added_ips[*]}"
|
||||||
|
fi
|
||||||
|
|
||||||
# Update if changed
|
# Update if changed
|
||||||
[[ "$(IFS=';'; echo "${current_tags[*]}")" != "$(IFS=';'; echo "${next_tags[*]}")" ]] && \
|
if [[ "$(IFS=';'; echo "${current_tags[*]}")" != "$(IFS=';'; echo "${next_tags[*]}")" ]]; then
|
||||||
$config_cmd set "${vmid}" -tags "$(IFS=';'; echo "${next_tags[*]}")"
|
$config_cmd set "${vmid}" -tags "$(IFS=';'; echo "${next_tags[*]}")" &>/dev/null
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if status changed
|
||||||
|
check_status_changed() {
|
||||||
|
local type="$1"
|
||||||
|
local current_status
|
||||||
|
|
||||||
|
case "$type" in
|
||||||
|
"lxc")
|
||||||
|
current_status=$(pct list 2>/dev/null | grep -v VMID)
|
||||||
|
[[ "${last_lxc_status}" == "${current_status}" ]] && return 1
|
||||||
|
last_lxc_status="${current_status}"
|
||||||
|
;;
|
||||||
|
"vm")
|
||||||
|
current_status=$(qm list 2>/dev/null | grep -v VMID)
|
||||||
|
[[ "${last_vm_status}" == "${current_status}" ]] && return 1
|
||||||
|
last_vm_status="${current_status}"
|
||||||
|
;;
|
||||||
|
"fw")
|
||||||
|
current_status=$(ifconfig 2>/dev/null | grep "^fw")
|
||||||
|
[[ "${last_net_interface}" == "${current_status}" ]] && return 1
|
||||||
|
last_net_interface="${current_status}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
check() {
|
check() {
|
||||||
@ -629,7 +813,7 @@ check() {
|
|||||||
time_since_last_lxc_status_check=$((current_time - last_lxc_status_check_time))
|
time_since_last_lxc_status_check=$((current_time - last_lxc_status_check_time))
|
||||||
if [[ "${LXC_STATUS_CHECK_INTERVAL}" -gt 0 ]] \
|
if [[ "${LXC_STATUS_CHECK_INTERVAL}" -gt 0 ]] \
|
||||||
&& [[ "${time_since_last_lxc_status_check}" -ge "${LXC_STATUS_CHECK_INTERVAL}" ]]; then
|
&& [[ "${time_since_last_lxc_status_check}" -ge "${LXC_STATUS_CHECK_INTERVAL}" ]]; then
|
||||||
echo "Checking lxc status..."
|
echo "Checking LXC status..."
|
||||||
last_lxc_status_check_time=${current_time}
|
last_lxc_status_check_time=${current_time}
|
||||||
if check_status_changed "lxc"; then
|
if check_status_changed "lxc"; then
|
||||||
update_all_tags "lxc"
|
update_all_tags "lxc"
|
||||||
@ -641,7 +825,7 @@ check() {
|
|||||||
time_since_last_vm_status_check=$((current_time - last_vm_status_check_time))
|
time_since_last_vm_status_check=$((current_time - last_vm_status_check_time))
|
||||||
if [[ "${VM_STATUS_CHECK_INTERVAL}" -gt 0 ]] \
|
if [[ "${VM_STATUS_CHECK_INTERVAL}" -gt 0 ]] \
|
||||||
&& [[ "${time_since_last_vm_status_check}" -ge "${VM_STATUS_CHECK_INTERVAL}" ]]; then
|
&& [[ "${time_since_last_vm_status_check}" -ge "${VM_STATUS_CHECK_INTERVAL}" ]]; then
|
||||||
echo "Checking vm status..."
|
echo "Checking VM status..."
|
||||||
last_vm_status_check_time=${current_time}
|
last_vm_status_check_time=${current_time}
|
||||||
if check_status_changed "vm"; then
|
if check_status_changed "vm"; then
|
||||||
update_all_tags "vm"
|
update_all_tags "vm"
|
||||||
@ -653,7 +837,7 @@ check() {
|
|||||||
time_since_last_fw_net_interface_check=$((current_time - last_fw_net_interface_check_time))
|
time_since_last_fw_net_interface_check=$((current_time - last_fw_net_interface_check_time))
|
||||||
if [[ "${FW_NET_INTERFACE_CHECK_INTERVAL}" -gt 0 ]] \
|
if [[ "${FW_NET_INTERFACE_CHECK_INTERVAL}" -gt 0 ]] \
|
||||||
&& [[ "${time_since_last_fw_net_interface_check}" -ge "${FW_NET_INTERFACE_CHECK_INTERVAL}" ]]; then
|
&& [[ "${time_since_last_fw_net_interface_check}" -ge "${FW_NET_INTERFACE_CHECK_INTERVAL}" ]]; then
|
||||||
echo "Checking fw net interface..."
|
echo "Checking network interfaces..."
|
||||||
last_fw_net_interface_check_time=${current_time}
|
last_fw_net_interface_check_time=${current_time}
|
||||||
if check_status_changed "fw"; then
|
if check_status_changed "fw"; then
|
||||||
update_all_tags "lxc"
|
update_all_tags "lxc"
|
||||||
@ -668,7 +852,7 @@ check() {
|
|||||||
local last_update_var="last_update_${type}_time"
|
local last_update_var="last_update_${type}_time"
|
||||||
local time_since_last_update=$((current_time - ${!last_update_var}))
|
local time_since_last_update=$((current_time - ${!last_update_var}))
|
||||||
if [ ${time_since_last_update} -ge ${FORCE_UPDATE_INTERVAL} ]; then
|
if [ ${time_since_last_update} -ge ${FORCE_UPDATE_INTERVAL} ]; then
|
||||||
echo "Force updating ${type} iptags..."
|
echo "Force updating ${type} tags..."
|
||||||
update_all_tags "$type"
|
update_all_tags "$type"
|
||||||
eval "${last_update_var}=${current_time}"
|
eval "${last_update_var}=${current_time}"
|
||||||
fi
|
fi
|
||||||
|
Loading…
x
Reference in New Issue
Block a user