Files
auto-macvlan/incus-macvlan.sh

129 lines
4.8 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# incus-macvlan.sh — pasang NIC macvlan + aktifkan DHCP di guest incus,
# supaya instance langsung dapat IP di LAN (mis. 192.168.200.x).
#
# Pakai:
# ./incus-macvlan.sh <instance> [device] [network]
# ./incus-macvlan.sh web1
# ./incus-macvlan.sh web1 eth1 eth200
#
# Opsi:
# --parent <iface> interface fisik host (default: dari default route host)
# --network <name> nama network macvlan (default: eth200)
# --device <name> nama NIC di guest (default: eth1)
# --create buat network macvlan kalau belum ada
# -h, --help bantuan
#
# Idempotent: aman dijalankan berulang. Kalau instance sudah punya NIC
# di network macvlan (termasuk dari profile), NIC tidak ditambahkan lagi.
set -euo pipefail
INSTANCE=""; DEVICE="eth1"; NETWORK="eth200"; PARENT=""; CREATE=0
POS=()
say(){ printf '%s\n' "$*"; }
die(){ printf 'error: %s\n' "$*" >&2; exit 1; }
while [ $# -gt 0 ]; do
case "$1" in
--parent) PARENT="${2:?--parent butuh nilai}"; shift 2 ;;
--network) NETWORK="${2:?--network butuh nilai}"; shift 2 ;;
--device) DEVICE="${2:?--device butuh nilai}"; shift 2 ;;
--create) CREATE=1; shift ;;
-h|--help) sed -n '2,20p' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;;
-*) die "opsi tak dikenal: $1" ;;
*) POS+=("$1"); shift ;;
esac
done
INSTANCE="${POS[0]:-}"
[ -n "${POS[1]:-}" ] && DEVICE="${POS[1]}"
[ -n "${POS[2]:-}" ] && NETWORK="${POS[2]}"
[ -n "$INSTANCE" ] || die "pakai: $(basename "$0") <instance> [device] [network]"
[[ "$DEVICE" =~ ^[A-Za-z0-9_.-]+$ ]] || die "nama device tidak valid: $DEVICE"
[[ "$NETWORK" =~ ^[A-Za-z0-9_.-]+$ ]] || die "nama network tidak valid: $NETWORK"
command -v incus >/dev/null 2>&1 || die "perintah 'incus' tidak ditemukan"
incus info "$INSTANCE" </dev/null >/dev/null 2>&1 || die "instance '$INSTANCE' tidak ditemukan"
if [ -z "$PARENT" ]; then
PARENT="$(ip route show default 2>/dev/null | awk '{print $5; exit}')"
PARENT="${PARENT:-enp2s0}"
fi
# ---- network macvlan ----
if incus network list -c n -f csv </dev/null 2>/dev/null | grep -qx "$NETWORK"; then
say "network '$NETWORK' sudah ada"
else
[ "$CREATE" = 1 ] || die "network '$NETWORK' belum ada (pakai --create, parent $PARENT)"
say "membuat network macvlan '$NETWORK' (parent $PARENT)"
incus network create "$NETWORK" --type=macvlan parent="$PARENT" </dev/null
fi
# ---- pastikan running ----
STATE="$(incus info "$INSTANCE" </dev/null | awk -F': ' '/^Status:/{print $2}')"
if [ "$STATE" != "RUNNING" ]; then
say "menyalakan instance '$INSTANCE'"
incus start "$INSTANCE" </dev/null
sleep 3
fi
# ---- pasang NIC (kalau belum ada NIC di network ini, termasuk dari profile) ----
if incus config show --expanded "$INSTANCE" </dev/null 2>/dev/null | grep -q "network: $NETWORK"; then
say "instance sudah punya NIC di network '$NETWORK' (dilewati)"
elif incus config device list "$INSTANCE" </dev/null | grep -qx "$DEVICE"; then
say "device '$DEVICE' sudah ada (dilewati)"
else
if incus config device add "$INSTANCE" "$DEVICE" nic network="$NETWORK" name="$DEVICE" </dev/null; then
say "NIC '$DEVICE' (network $NETWORK) ditambahkan"
else
say "peringatan: gagal menambah NIC '$DEVICE' (lanjut cek DHCP)"
fi
fi
# ---- aktifkan DHCP di guest untuk semua NIC tanpa IPv4 ----
say "mengaktifkan DHCP di guest"
incus exec "$INSTANCE" -- sh -c '
configure_one() {
dev="$1"
if systemctl is-active --quiet NetworkManager 2>/dev/null; then
nmcli device connect "$dev" >/dev/null 2>&1 || true
elif systemctl is-active --quiet systemd-networkd 2>/dev/null || [ -d /etc/systemd/network ]; then
printf "[Match]\nName=%s\n[Network]\nDHCP=yes\n" "$dev" > "/etc/systemd/network/20-$dev.network"
elif command -v dhcpcd >/dev/null 2>&1; then dhcpcd "$dev" >/dev/null 2>&1 || true
elif command -v dhclient >/dev/null 2>&1; then dhclient "$dev" >/dev/null 2>&1 || true
elif command -v udhcpc >/dev/null 2>&1; then udhcpc -i "$dev" >/dev/null 2>&1 || true
fi
}
for i in /sys/class/net/*; do
dev=$(basename "$i"); [ "$dev" = lo ] && continue
ip -4 addr show "$dev" 2>/dev/null | grep -q "inet " && continue
configure_one "$dev"
done
systemctl restart systemd-networkd >/dev/null 2>&1 || true
' </dev/null || say "peringatan: konfigurasi DHCP di guest gagal (lanjut)"
# ---- tunggu IP LAN ----
IP=""
for _ in $(seq 1 20); do
IP="$(incus list "$INSTANCE" -c 4 -f csv </dev/null 2>/dev/null \
| tr ',' '\n' | grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' \
| grep -vE '^(10\.|127\.)' | head -1 || true)"
[ -n "$IP" ] && break
sleep 1
done
say ""
if [ -n "$IP" ]; then
say "instance : $INSTANCE"
say "network : $NETWORK (parent $PARENT)"
say "IP LAN : $IP"
say "SSH : ssh root@$IP"
else
say "instance : $INSTANCE"
say "IP LAN : belum terdeteksi"
say "cek : incus exec $INSTANCE -- ip -4 addr"
exit 1
fi