Refactor: IP-Tag (#10558)

This commit is contained in:
CanbiZ (MickLesk)
2026-01-05 15:23:58 +01:00
committed by GitHub
parent 0e2bbc2733
commit 3a35cc8282
+157 -126
View File
@@ -107,7 +107,6 @@ migrate_config() {
fi fi
} }
# Update existing installation # Update existing installation
update_installation() { update_installation() {
msg_info "Updating IP-Tag Scripts" msg_info "Updating IP-Tag Scripts"
@@ -207,15 +206,15 @@ install_command_only() {
echo -e "\n${YW}Configuration file already exists.${CL}" echo -e "\n${YW}Configuration file already exists.${CL}"
read -p "Do you want to reconfigure tag format? (y/n): " reconfigure read -p "Do you want to reconfigure tag format? (y/n): " reconfigure
case $reconfigure in case $reconfigure in
[Yy]*) [Yy]*)
interactive_config_setup_command interactive_config_setup_command
msg_info "Updating Configuration" msg_info "Updating Configuration"
generate_config >/opt/iptag/iptag.conf generate_config >/opt/iptag/iptag.conf
msg_ok "Updated configuration file" msg_ok "Updated configuration file"
;; ;;
*) *)
msg_ok "Keeping existing configuration file" msg_ok "Keeping existing configuration file"
;; ;;
esac esac
fi fi
@@ -284,24 +283,24 @@ interactive_config_setup_command() {
while true; do while true; do
read -p "Enter your choice (1-3) [1]: " tag_choice read -p "Enter your choice (1-3) [1]: " tag_choice
case ${tag_choice:-1} in case ${tag_choice:-1} in
1) 1)
TAG_FORMAT="last_two_octets" TAG_FORMAT="last_two_octets"
echo -e "${GN}✓ Selected: last_two_octets${CL}" echo -e "${GN}✓ Selected: last_two_octets${CL}"
break break
;; ;;
2) 2)
TAG_FORMAT="last_octet" TAG_FORMAT="last_octet"
echo -e "${GN}✓ Selected: last_octet${CL}" echo -e "${GN}✓ Selected: last_octet${CL}"
break break
;; ;;
3) 3)
TAG_FORMAT="full" TAG_FORMAT="full"
echo -e "${GN}✓ Selected: full${CL}" echo -e "${GN}✓ Selected: full${CL}"
break break
;; ;;
*) *)
echo -e "${RD}Please enter 1, 2, or 3.${CL}" echo -e "${RD}Please enter 1, 2, or 3.${CL}"
;; ;;
esac esac
done done
@@ -322,24 +321,24 @@ interactive_config_setup() {
while true; do while true; do
read -p "Enter your choice (1-3) [1]: " tag_choice read -p "Enter your choice (1-3) [1]: " tag_choice
case ${tag_choice:-1} in case ${tag_choice:-1} in
1) 1)
TAG_FORMAT="last_two_octets" TAG_FORMAT="last_two_octets"
echo -e "${GN}✓ Selected: last_two_octets${CL}" echo -e "${GN}✓ Selected: last_two_octets${CL}"
break break
;; ;;
2) 2)
TAG_FORMAT="last_octet" TAG_FORMAT="last_octet"
echo -e "${GN}✓ Selected: last_octet${CL}" echo -e "${GN}✓ Selected: last_octet${CL}"
break break
;; ;;
3) 3)
TAG_FORMAT="full" TAG_FORMAT="full"
echo -e "${GN}✓ Selected: full${CL}" echo -e "${GN}✓ Selected: full${CL}"
break break
;; ;;
*) *)
echo -e "${RD}Please enter 1, 2, or 3.${CL}" echo -e "${RD}Please enter 1, 2, or 3.${CL}"
;; ;;
esac esac
done done
@@ -646,21 +645,40 @@ get_vm_ips() {
echo "$unique_ips" echo "$unique_ips"
} }
# Cache for configs to avoid repeated reads
declare -A CONFIG_CACHE
declare -A IP_CACHE
# Update tags for container or VM # Update tags for container or VM
update_tags() { update_tags() {
local type="$1" vmid="$2" local type="$1" vmid="$2"
local current_ips_full local current_ips_full
local current_tags_raw=""
if [[ "$type" == "lxc" ]]; then # Get IPs with caching
current_ips_full=$(get_lxc_ips "${vmid}") local cache_key="${type}_${vmid}"
while IFS= read -r line; do if [[ -n "${IP_CACHE[$cache_key]:-}" ]]; then
[[ "$line" == tags:* ]] && current_tags_raw="${line#tags: }" && break current_ips_full="${IP_CACHE[$cache_key]}"
done < <(pct config "$vmid" 2>/dev/null) debug_log "$type $vmid: using cached IPs"
else
if [[ "$type" == "lxc" ]]; then
current_ips_full=$(get_lxc_ips "${vmid}")
else
current_ips_full=$(get_vm_ips "${vmid}")
fi
IP_CACHE[$cache_key]="$current_ips_full"
fi
# Get current tags (optimized file reading)
if [[ "$type" == "lxc" ]]; then
local config_file="/etc/pve/lxc/${vmid}.conf"
if [[ -f "$config_file" ]]; then
current_tags_raw=$(grep "^tags:" "$config_file" 2>/dev/null | cut -d: -f2 | sed 's/^[[:space:]]*//')
fi
else else
current_ips_full=$(get_vm_ips "${vmid}")
local vm_config="/etc/pve/qemu-server/${vmid}.conf" local vm_config="/etc/pve/qemu-server/${vmid}.conf"
if [[ -f "$vm_config" ]]; then if [[ -f "$vm_config" ]]; then
local current_tags_raw=$(grep "^tags:" "$vm_config" 2>/dev/null | cut -d: -f2 | sed 's/^[[:space:]]*//') current_tags_raw=$(grep "^tags:" "$vm_config" 2>/dev/null | cut -d: -f2 | sed 's/^[[:space:]]*//')
fi fi
fi fi
@@ -818,11 +836,15 @@ update_tags() {
update_all_tags() { update_all_tags() {
local type="$1" vmids count=0 local type="$1" vmids count=0
# Get list of all containers/VMs
if [[ "$type" == "lxc" ]]; then if [[ "$type" == "lxc" ]]; then
vmids=($(pct list 2>/dev/null | grep -v VMID | awk '{print $1}')) vmids=($(pct list 2>/dev/null | grep -v VMID | awk '{print $1}'))
else else
local all_vm_configs=($(ls /etc/pve/qemu-server/*.conf 2>/dev/null | sed 's/.*\/\([0-9]*\)\.conf/\1/' | sort -n)) # More efficient: direct file listing instead of ls+sed
vmids=("${all_vm_configs[@]}") vmids=()
for conf in /etc/pve/qemu-server/*.conf 2>/dev/null; do
[[ -f "$conf" ]] && vmids+=("${conf##*/}" | sed 's/\.conf$//')
done
fi fi
count=${#vmids[@]} count=${#vmids[@]}
@@ -830,14 +852,16 @@ update_all_tags() {
# Display processing header with color # Display processing header with color
if [[ "$type" == "lxc" ]]; then if [[ "$type" == "lxc" ]]; then
log_info "Processing ${WHITE}${count}${NC} LXC container(s) sequentially" log_info "Processing ${WHITE}${count}${NC} LXC container(s)"
else else
log_info "Processing ${WHITE}${count}${NC} virtual machine(s) sequentially" log_info "Processing ${WHITE}${count}${NC} virtual machine(s)"
fi fi
# Process each VM/LXC container sequentially # Process each VM/LXC container
local processed=0
for vmid in "${vmids[@]}"; do for vmid in "${vmids[@]}"; do
update_tags "$type" "$vmid" update_tags "$type" "$vmid"
((processed++))
done done
# Add completion message # Add completion message
@@ -848,32 +872,25 @@ update_all_tags() {
fi fi
} }
# Check if status changed
check_status_changed() {
local type="$1" current
case "$type" in
"lxc") current=$(pct list 2>/dev/null | grep -v VMID) ;;
"vm") current=$(ls -la /etc/pve/qemu-server/*.conf 2>/dev/null) ;;
"fw") current=$(ip link show type bridge 2>/dev/null) ;;
esac
local last_var="last_${type}_status"
[[ "${!last_var}" == "$current" ]] && return 1
eval "$last_var='$current'"
return 0
}
# Main check function # Main check function
check() { check() {
local current_time=$(date +%s) local start_time=$(date +%s)
# Simple periodic check - always update both LXC and VM every loop
log_info "Starting periodic check" log_info "Starting periodic check"
# Clear caches before each run
CONFIG_CACHE=()
IP_CACHE=()
# Update LXC containers # Update LXC containers
update_all_tags "lxc" update_all_tags "lxc"
# Update VMs # Update VMs
update_all_tags "vm" update_all_tags "vm"
local end_time=$(date +%s)
local duration=$((end_time - start_time))
log_success "Check completed in ${WHITE}${duration}${NC} seconds"
} }
# Main loop # Main loop
@@ -917,40 +934,54 @@ get_lxc_ips() {
local ips="" local ips=""
# Method 1: Check Proxmox config for static IP # Method 1: Check Proxmox config for ALL static IPs (multiple interfaces)
local pve_lxc_config="/etc/pve/lxc/${vmid}.conf" local pve_lxc_config="/etc/pve/lxc/${vmid}.conf"
if [[ -f "$pve_lxc_config" ]]; then if [[ -f "$pve_lxc_config" ]]; then
local static_ip=$(grep -E "^net[0-9]+:" "$pve_lxc_config" 2>/dev/null | grep -oE 'ip=([0-9]{1,3}\.){3}[0-9]{1,3}' | cut -d'=' -f2 | head -1) local static_ips=$(grep -E "^net[0-9]+:" "$pve_lxc_config" 2>/dev/null | grep -oE 'ip=([0-9]{1,3}\.){3}[0-9]{1,3}' | cut -d'=' -f2)
if [[ -n "$static_ip" && "$static_ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then if [[ -n "$static_ips" ]]; then
debug_log "lxc $vmid: found static IP $static_ip in config" while IFS= read -r ip; do
ips="$static_ip" if [[ "$ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
debug_log "lxc $vmid: found static IP $ip in config"
ips="${ips}${ips:+ }${ip}"
fi
done <<< "$static_ips"
fi fi
fi fi
# Method 2: ARP table lookup if no static IP # Method 2: ARP table lookup for ALL MAC addresses if no static IPs found
if [[ -z "$ips" && -f "$pve_lxc_config" ]]; then if [[ -z "$ips" && -f "$pve_lxc_config" ]]; then
local mac_addr=$(grep -Eo 'hwaddr=([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}' "$pve_lxc_config" | head -1 | cut -d'=' -f2) local mac_addrs=$(grep -Eo 'hwaddr=([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}' "$pve_lxc_config" | cut -d'=' -f2)
if [[ -n "$mac_addr" ]]; then if [[ -n "$mac_addrs" ]]; then
local bridge_name=$(grep -Eo 'bridge=[^,]+' "$pve_lxc_config" | head -1 | cut -d'=' -f2) while IFS= read -r mac_addr; do
local arp_ip=$(ip neighbor show | grep "$mac_addr" | grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' | head -1) [[ -z "$mac_addr" ]] && continue
if [[ -n "$arp_ip" && "$arp_ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then local arp_ip=$(ip neighbor show | grep -i "$mac_addr" | grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' | head -1)
debug_log "lxc $vmid: found IP $arp_ip via ARP table" if [[ -n "$arp_ip" && "$arp_ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
ips="$arp_ip" debug_log "lxc $vmid: found IP $arp_ip via ARP table for MAC $mac_addr"
fi ips="${ips}${ips:+ }${arp_ip}"
fi
done <<< "$mac_addrs"
fi fi
fi fi
# Method 3: Direct container command if ARP failed # Method 3: Direct container command to get ALL IPs if previous methods failed
if [[ -z "$ips" ]]; then if [[ -z "$ips" ]]; then
local container_ip=$(timeout 5s pct exec "$vmid" -- ip -4 addr show 2>/dev/null | grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' | grep -v '127.0.0.1' | head -1) local container_ips=$(timeout 5s pct exec "$vmid" -- ip -4 addr show 2>/dev/null | grep -oE 'inet ([0-9]{1,3}\.){3}[0-9]{1,3}' | awk '{print $2}' | grep -v '127.0.0.1')
if [[ -n "$container_ip" ]] && is_valid_ipv4 "$container_ip"; then if [[ -n "$container_ips" ]]; then
debug_log "lxc $vmid: found IP $container_ip via pct exec" while IFS= read -r ip; do
ips="$container_ip" if is_valid_ipv4 "$ip"; then
debug_log "lxc $vmid: found IP $ip via pct exec"
ips="${ips}${ips:+ }${ip}"
fi
done <<< "$container_ips"
fi fi
fi fi
debug_log "lxc $vmid: final IPs: '$ips'" # Remove duplicates and clean up
echo "$ips" local unique_ips=$(echo "$ips" | tr ' ' '\n' | sort -u | tr '\n' ' ')
unique_ips="${unique_ips% }"
debug_log "lxc $vmid: final IPs: '$unique_ips'"
echo "$unique_ips"
} }
main main
@@ -967,28 +998,28 @@ echo -e "${RD}4)${CL} Cancel"
while true; do while true; do
read -p "Enter your choice (1-4): " choice read -p "Enter your choice (1-4): " choice
case $choice in case $choice in
1) 1)
INSTALL_MODE="service" INSTALL_MODE="service"
echo -e "${GN}✓ Selected: Service installation${CL}" echo -e "${GN}✓ Selected: Service installation${CL}"
break break
;; ;;
2) 2)
INSTALL_MODE="command" INSTALL_MODE="command"
echo -e "${GN}✓ Selected: Command-only installation${CL}" echo -e "${GN}✓ Selected: Command-only installation${CL}"
break break
;; ;;
3) 3)
echo -e "${GN}✓ Selected: Update installation${CL}" echo -e "${GN}✓ Selected: Update installation${CL}"
update_installation update_installation
exit 0 exit 0
;; ;;
4) 4)
msg_error "Action cancelled." msg_error "Action cancelled."
exit 0 exit 0
;; ;;
*) *)
msg_error "Please enter 1, 2, 3, or 4." msg_error "Please enter 1, 2, 3, or 4."
;; ;;
esac esac
done done
@@ -1043,15 +1074,15 @@ if [[ "$INSTALL_MODE" == "service" ]]; then
echo -e "\n${YW}Configuration file already exists.${CL}" echo -e "\n${YW}Configuration file already exists.${CL}"
read -p "Do you want to reconfigure tag format and loop interval? (y/n): " reconfigure read -p "Do you want to reconfigure tag format and loop interval? (y/n): " reconfigure
case $reconfigure in case $reconfigure in
[Yy]*) [Yy]*)
interactive_config_setup interactive_config_setup
msg_info "Updating Configuration" msg_info "Updating Configuration"
generate_config >/opt/iptag/iptag.conf generate_config >/opt/iptag/iptag.conf
msg_ok "Updated configuration file" msg_ok "Updated configuration file"
;; ;;
*) *)
msg_ok "Keeping existing configuration file" msg_ok "Keeping existing configuration file"
;; ;;
esac esac
fi fi