Initial commit
This commit is contained in:
commit
dfd81074ae
768
install-snmpsim-lab.sh
Normal file
768
install-snmpsim-lab.sh
Normal file
@ -0,0 +1,768 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# =============================================================================
|
||||||
|
# install-snmpsim-lab.sh
|
||||||
|
#
|
||||||
|
# Installs the SevOne SNMP Simulation Lab into /opt/snmpsim
|
||||||
|
# All 10 devices use SNMPv2c (community: public)
|
||||||
|
#
|
||||||
|
# Components:
|
||||||
|
# - snmpsim-lextudio : 10 faux Cisco SNMP agents
|
||||||
|
# - trap-generator.sh : Random SNMP trap sender
|
||||||
|
# - nflow-generator : Synthetic NetFlow v5 exporter
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# ./install-snmpsim-lab.sh [OPTIONS]
|
||||||
|
#
|
||||||
|
# Options:
|
||||||
|
# -v, --vm-ip IP address of this VM (SNMP agents bind to this IP)
|
||||||
|
# -t, --trap-host IP address of the SNMP trap destination (SevOne)
|
||||||
|
# -n, --netflow-host IP address of the NetFlow collector (SevOne)
|
||||||
|
# -p, --netflow-port UDP port for NetFlow (default: 9996)
|
||||||
|
# -T, --trap-port UDP port for SNMP traps (default: 162)
|
||||||
|
# -h, --help Show this help message
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
# ./install-snmpsim-lab.sh \
|
||||||
|
# --vm-ip 9.60.154.118 \
|
||||||
|
# --trap-host 9.60.151.170 \
|
||||||
|
# --netflow-host 9.60.151.170
|
||||||
|
#
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# ── Defaults ─────────────────────────────────────────────────────────────────
|
||||||
|
INSTALL_DIR="/opt/snmpsim"
|
||||||
|
SNMPSIM_USER="snmpsim"
|
||||||
|
NETFLOW_PORT="9996"
|
||||||
|
TRAP_PORT="162"
|
||||||
|
VM_IP=""
|
||||||
|
TRAP_HOST=""
|
||||||
|
NETFLOW_HOST=""
|
||||||
|
|
||||||
|
# ── Colours for output ────────────────────────────────────────────────────────
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
CYAN='\033[0;36m'
|
||||||
|
NC='\033[0m' # No Colour
|
||||||
|
|
||||||
|
info() { echo -e "${CYAN}[INFO]${NC} $*"; }
|
||||||
|
ok() { echo -e "${GREEN}[OK]${NC} $*"; }
|
||||||
|
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
|
||||||
|
error() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
|
||||||
|
section() { echo -e "\n${BLUE}══════════════════════════════════════════${NC}"; \
|
||||||
|
echo -e "${BLUE} $*${NC}"; \
|
||||||
|
echo -e "${BLUE}══════════════════════════════════════════${NC}"; }
|
||||||
|
|
||||||
|
# ── Usage ─────────────────────────────────────────────────────────────────────
|
||||||
|
usage() {
|
||||||
|
cat << EOF
|
||||||
|
|
||||||
|
Usage: $(basename "$0") [OPTIONS]
|
||||||
|
|
||||||
|
OPTIONS:
|
||||||
|
-v, --vm-ip IP address of this VM that SNMP agents will bind to [REQUIRED]
|
||||||
|
-t, --trap-host Destination IP for SNMP traps (SevOne) [REQUIRED]
|
||||||
|
-n, --netflow-host Destination IP for NetFlow (SevOne) [REQUIRED]
|
||||||
|
-p, --netflow-port UDP port for NetFlow collector (default: 9996)
|
||||||
|
-T, --trap-port UDP port for SNMP trap receiver (default: 162)
|
||||||
|
-h, --help Show this help
|
||||||
|
|
||||||
|
EXAMPLE:
|
||||||
|
$(basename "$0") \\
|
||||||
|
--vm-ip 9.60.154.118 \\
|
||||||
|
--trap-host 9.60.151.170 \\
|
||||||
|
--netflow-host 9.60.151.170
|
||||||
|
|
||||||
|
EOF
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Parse arguments ───────────────────────────────────────────────────────────
|
||||||
|
if [[ $# -eq 0 ]]; then usage; fi
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
-v|--vm-ip) VM_IP="$2"; shift 2 ;;
|
||||||
|
-t|--trap-host) TRAP_HOST="$2"; shift 2 ;;
|
||||||
|
-n|--netflow-host) NETFLOW_HOST="$2"; shift 2 ;;
|
||||||
|
-p|--netflow-port) NETFLOW_PORT="$2"; shift 2 ;;
|
||||||
|
-T|--trap-port) TRAP_PORT="$2"; shift 2 ;;
|
||||||
|
-h|--help) usage ;;
|
||||||
|
*) error "Unknown option: $1"; usage ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# ── Validate required arguments ───────────────────────────────────────────────
|
||||||
|
MISSING=0
|
||||||
|
[[ -z "$VM_IP" ]] && { error "--vm-ip is required"; MISSING=1; }
|
||||||
|
[[ -z "$TRAP_HOST" ]] && { error "--trap-host is required"; MISSING=1; }
|
||||||
|
[[ -z "$NETFLOW_HOST" ]] && { error "--netflow-host is required"; MISSING=1; }
|
||||||
|
[[ $MISSING -eq 1 ]] && { echo ""; usage; }
|
||||||
|
|
||||||
|
# ── Must run as root ──────────────────────────────────────────────────────────
|
||||||
|
if [[ $EUID -ne 0 ]]; then
|
||||||
|
error "This script must be run as root (sudo)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── Summary ───────────────────────────────────────────────────────────────────
|
||||||
|
echo ""
|
||||||
|
echo -e "${BLUE}╔══════════════════════════════════════════════════╗${NC}"
|
||||||
|
echo -e "${BLUE}║ SevOne SNMP Lab Installer ║${NC}"
|
||||||
|
echo -e "${BLUE}╚══════════════════════════════════════════════════╝${NC}"
|
||||||
|
echo ""
|
||||||
|
echo -e " Install directory : ${CYAN}${INSTALL_DIR}${NC}"
|
||||||
|
echo -e " VM IP (SNMP bind) : ${CYAN}${VM_IP}${NC}"
|
||||||
|
echo -e " Trap destination : ${CYAN}${TRAP_HOST}:${TRAP_PORT}${NC}"
|
||||||
|
echo -e " NetFlow destination: ${CYAN}${NETFLOW_HOST}:${NETFLOW_PORT}${NC}"
|
||||||
|
echo ""
|
||||||
|
read -rp "Proceed with installation? [y/N] " CONFIRM
|
||||||
|
[[ "$CONFIRM" =~ ^[Yy]$ ]] || { echo "Aborted."; exit 0; }
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
section "Step 1: System dependencies"
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
# Detect package manager
|
||||||
|
if command -v apt-get &>/dev/null; then
|
||||||
|
PKG_MGR="apt"
|
||||||
|
elif command -v dnf &>/dev/null; then
|
||||||
|
PKG_MGR="dnf"
|
||||||
|
elif command -v yum &>/dev/null; then
|
||||||
|
PKG_MGR="yum"
|
||||||
|
else
|
||||||
|
error "Cannot detect package manager (apt/dnf/yum). Install dependencies manually."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
info "Package manager: $PKG_MGR"
|
||||||
|
|
||||||
|
install_pkg() {
|
||||||
|
info "Installing: $*"
|
||||||
|
case $PKG_MGR in
|
||||||
|
apt) DEBIAN_FRONTEND=noninteractive NEEDRESTART_MODE=a apt-get install -y -qq -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" "$@" ;;
|
||||||
|
dnf) dnf install -y "$@" -q ;;
|
||||||
|
yum) yum install -y "$@" -q ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Update package index
|
||||||
|
case $PKG_MGR in
|
||||||
|
apt)
|
||||||
|
DEBIAN_FRONTEND=noninteractive apt-get update -qq
|
||||||
|
DEBIAN_FRONTEND=noninteractive NEEDRESTART_MODE=a apt-get upgrade -y -qq -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold"
|
||||||
|
;;
|
||||||
|
dnf|yum) : ;; # no-op, dnf/yum update on install
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Core dependencies
|
||||||
|
install_pkg python3 python3-pip
|
||||||
|
install_pkg snmp snmp-mibs-downloader 2>/dev/null || install_pkg net-snmp-utils 2>/dev/null || \
|
||||||
|
warn "Could not install net-snmp-utils — snmpwalk/snmptrap may be unavailable"
|
||||||
|
install_pkg git curl wget
|
||||||
|
|
||||||
|
# Go (for nflow-generator)
|
||||||
|
if ! command -v go &>/dev/null; then
|
||||||
|
info "Installing Go..."
|
||||||
|
case $PKG_MGR in
|
||||||
|
apt) install_pkg golang-go ;;
|
||||||
|
dnf|yum) install_pkg golang ;;
|
||||||
|
esac
|
||||||
|
else
|
||||||
|
ok "Go already installed: $(go version)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
ok "System dependencies installed"
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
section "Step 2: Create snmpsim user and directory structure"
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
if id "$SNMPSIM_USER" &>/dev/null; then
|
||||||
|
ok "User '$SNMPSIM_USER' already exists"
|
||||||
|
else
|
||||||
|
useradd -r -s /sbin/nologin "$SNMPSIM_USER"
|
||||||
|
ok "Created user: $SNMPSIM_USER"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Main directories
|
||||||
|
mkdir -p "${INSTALL_DIR}"/{data,logs,run}
|
||||||
|
for port in $(seq 10000 10009); do
|
||||||
|
mkdir -p "${INSTALL_DIR}/data/port-${port}"
|
||||||
|
done
|
||||||
|
|
||||||
|
# PID file directory
|
||||||
|
mkdir -p /var/run/snmpsim.commands.responder
|
||||||
|
|
||||||
|
# Ownership
|
||||||
|
chown -R "${SNMPSIM_USER}:${SNMPSIM_USER}" "${INSTALL_DIR}"
|
||||||
|
chown "${SNMPSIM_USER}:${SNMPSIM_USER}" /var/run/snmpsim.commands.responder
|
||||||
|
|
||||||
|
ok "Directory structure created: ${INSTALL_DIR}"
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
section "Step 3: Install snmpsim-lextudio"
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
if command -v pip3 &>/dev/null; then
|
||||||
|
pip3 install --quiet snmpsim
|
||||||
|
elif command -v pip &>/dev/null; then
|
||||||
|
pip install --quiet snmpsim-lextudio
|
||||||
|
else
|
||||||
|
error "pip not found. Cannot install snmpsim."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Find the installed binary
|
||||||
|
SNMPSIM_BIN=$(command -v snmpsim-command-responder 2>/dev/null || \
|
||||||
|
find /usr /root ~/.local -name "snmpsim-command-responder" 2>/dev/null | head -1)
|
||||||
|
|
||||||
|
if [[ -z "$SNMPSIM_BIN" ]]; then
|
||||||
|
error "snmpsim-command-responder not found after install. Check pip output above."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
ok "snmpsim installed: $SNMPSIM_BIN"
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
section "Step 4: Generate SNMP device data files"
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
cat > "${INSTALL_DIR}/generate_devices.py" << PYEOF
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Generate 10 Cisco .snmprec files for snmpsim lab.
|
||||||
|
Each device gets a port-NNNNN/public.snmprec file.
|
||||||
|
Counters use the snmpsim numeric variation module for live incrementing.
|
||||||
|
"""
|
||||||
|
import os, random
|
||||||
|
|
||||||
|
BASE_OUTPUT_DIR = "${INSTALL_DIR}/data"
|
||||||
|
|
||||||
|
DEVICES = [
|
||||||
|
("core-sw-01", "Cisco IOS Software, Catalyst 6500 Software (s72033_rp-ADVENTERPRISEK9_WAN-M), Version 15.1(2)SY14", "1.3.6.1.4.1.9.1.282", 10000),
|
||||||
|
("core-sw-02", "Cisco IOS Software, Catalyst 6500 Software (s72033_rp-ADVENTERPRISEK9_WAN-M), Version 15.1(2)SY14", "1.3.6.1.4.1.9.1.282", 10001),
|
||||||
|
("dist-sw-01", "Cisco IOS Software, Catalyst 4500 Software (cat4500e-UNIVERSALK9-M), Version 15.2(4)E10", "1.3.6.1.4.1.9.1.659", 10002),
|
||||||
|
("dist-sw-02", "Cisco IOS Software, Catalyst 4500 Software (cat4500e-UNIVERSALK9-M), Version 15.2(4)E10", "1.3.6.1.4.1.9.1.659", 10003),
|
||||||
|
("access-sw-01", "Cisco IOS Software, Catalyst 3750 Software (C3750E-UNIVERSALK9-M), Version 15.2(4)E9", "1.3.6.1.4.1.9.1.516", 10004),
|
||||||
|
("access-sw-02", "Cisco IOS Software, Catalyst 3750 Software (C3750E-UNIVERSALK9-M), Version 15.2(4)E9", "1.3.6.1.4.1.9.1.516", 10005),
|
||||||
|
("access-sw-03", "Cisco IOS Software, Catalyst 3750 Software (C3750E-UNIVERSALK9-M), Version 15.2(4)E9", "1.3.6.1.4.1.9.1.516", 10006),
|
||||||
|
("rtr-01", "Cisco IOS Software, Version 15.7(3)M8, RELEASE SOFTWARE (fc2) ISR 4321", "1.3.6.1.4.1.9.1.1861", 10007),
|
||||||
|
("rtr-02", "Cisco IOS Software, Version 15.7(3)M8, RELEASE SOFTWARE (fc2) ISR 4321", "1.3.6.1.4.1.9.1.1861", 10008),
|
||||||
|
("fw-01", "Cisco Adaptive Security Appliance Software Version 9.16(4)19", "1.3.6.1.4.1.9.1.1902", 10009),
|
||||||
|
]
|
||||||
|
|
||||||
|
SWITCH_IFACES = [
|
||||||
|
("GigabitEthernet0/1", 1000000000),
|
||||||
|
("GigabitEthernet0/2", 1000000000),
|
||||||
|
("GigabitEthernet0/3", 1000000000),
|
||||||
|
("GigabitEthernet0/4", 1000000000),
|
||||||
|
("GigabitEthernet0/5", 1000000000),
|
||||||
|
("TenGigabitEthernet1/1", 10000000000),
|
||||||
|
("TenGigabitEthernet1/2", 10000000000),
|
||||||
|
]
|
||||||
|
ROUTER_IFACES = [
|
||||||
|
("GigabitEthernet0/0/0", 1000000000),
|
||||||
|
("GigabitEthernet0/0/1", 1000000000),
|
||||||
|
("Serial0/1/0", 1544000),
|
||||||
|
]
|
||||||
|
FW_IFACES = [
|
||||||
|
("GigabitEthernet0/0", 1000000000),
|
||||||
|
("GigabitEthernet0/1", 1000000000),
|
||||||
|
("GigabitEthernet0/2", 1000000000),
|
||||||
|
("Management0/0", 1000000000),
|
||||||
|
]
|
||||||
|
|
||||||
|
MAX32 = 4294967295
|
||||||
|
|
||||||
|
def rand_mac(seed):
|
||||||
|
random.seed(seed)
|
||||||
|
return "".join(f"{random.randint(0,255):02x}" for _ in range(6))
|
||||||
|
|
||||||
|
def counter(initial, offset, deviation=0):
|
||||||
|
p = f"initial={initial},offset={offset},cumulative=1,min=0,max={MAX32},wrap=1"
|
||||||
|
if deviation: p += f",deviation={deviation}"
|
||||||
|
return ("65:numeric", p)
|
||||||
|
|
||||||
|
def gauge(initial, lo, hi, deviation):
|
||||||
|
return ("66:numeric", f"initial={initial},min={lo},max={hi},deviation={deviation},rate=0")
|
||||||
|
|
||||||
|
def timeticks(initial):
|
||||||
|
return ("67:numeric", f"initial={initial},offset=100,cumulative=1,min=0,max={MAX32}")
|
||||||
|
|
||||||
|
def ln(oid, tv):
|
||||||
|
return f"{oid}|{tv[0]}|{tv[1]}"
|
||||||
|
|
||||||
|
def make_snmprec(idx, hostname, descr, sysoid, ifaces):
|
||||||
|
random.seed(idx * 1000)
|
||||||
|
uptime = random.randint(500_000, 80_000_000)
|
||||||
|
cpu_base = random.randint(5, 35)
|
||||||
|
mem_used = random.randint(50_000_000, 200_000_000)
|
||||||
|
mem_free = random.randint(20_000_000, 100_000_000)
|
||||||
|
lines = []
|
||||||
|
|
||||||
|
lines.append(f"1.3.6.1.2.1.1.1.0|4|{descr}")
|
||||||
|
lines.append(f"1.3.6.1.2.1.1.2.0|6|{sysoid}")
|
||||||
|
lines.append(ln("1.3.6.1.2.1.1.3.0", timeticks(uptime)))
|
||||||
|
lines.append(f"1.3.6.1.2.1.1.4.0|4|noc@lab.local")
|
||||||
|
lines.append(f"1.3.6.1.2.1.1.5.0|4|{hostname}.lab.local")
|
||||||
|
lines.append(f"1.3.6.1.2.1.1.6.0|4|Lab - Rack A")
|
||||||
|
lines.append(f"1.3.6.1.2.1.1.7.0|2|78")
|
||||||
|
lines.append(f"1.3.6.1.2.1.2.1.0|2|{len(ifaces)}")
|
||||||
|
|
||||||
|
for i, (ifdescr, ifspeed) in enumerate(ifaces, start=1):
|
||||||
|
random.seed(idx * 200 + i)
|
||||||
|
mac = rand_mac(idx * 100 + i)
|
||||||
|
oper = 1 if i < len(ifaces) else 2
|
||||||
|
in_oct = random.randint(10_000_000, 999_000_000)
|
||||||
|
out_oct = random.randint(10_000_000, 999_000_000)
|
||||||
|
in_pkt = in_oct // random.randint(64, 512)
|
||||||
|
out_pkt = out_oct // random.randint(64, 512)
|
||||||
|
err = random.randint(0, 50)
|
||||||
|
disc = random.randint(0, 30)
|
||||||
|
if ifspeed >= 10_000_000_000:
|
||||||
|
oo, od = random.randint(5_000_000, 20_000_000), random.randint(5_000, 20_000)
|
||||||
|
elif ifspeed >= 1_000_000_000:
|
||||||
|
oo, od = random.randint(500_000, 5_000_000), random.randint(500, 5_000)
|
||||||
|
else:
|
||||||
|
oo, od = random.randint(10_000, 100_000), random.randint(10, 100)
|
||||||
|
|
||||||
|
lines += [
|
||||||
|
f"1.3.6.1.2.1.2.2.1.1.{i}|2|{i}",
|
||||||
|
f"1.3.6.1.2.1.2.2.1.2.{i}|4|{ifdescr}",
|
||||||
|
f"1.3.6.1.2.1.2.2.1.3.{i}|2|6",
|
||||||
|
f"1.3.6.1.2.1.2.2.1.4.{i}|2|1500",
|
||||||
|
f"1.3.6.1.2.1.2.2.1.5.{i}|66|{ifspeed}",
|
||||||
|
f"1.3.6.1.2.1.2.2.1.6.{i}|4x|{mac}",
|
||||||
|
f"1.3.6.1.2.1.2.2.1.7.{i}|2|1",
|
||||||
|
f"1.3.6.1.2.1.2.2.1.8.{i}|2|{oper}",
|
||||||
|
ln(f"1.3.6.1.2.1.2.2.1.10.{i}", counter(in_oct, oo, int(oo*0.1))),
|
||||||
|
ln(f"1.3.6.1.2.1.2.2.1.11.{i}", counter(in_pkt, od, int(od*0.1))),
|
||||||
|
ln(f"1.3.6.1.2.1.2.2.1.13.{i}", counter(disc, 0, 1)),
|
||||||
|
ln(f"1.3.6.1.2.1.2.2.1.14.{i}", counter(err, 0, 1)),
|
||||||
|
ln(f"1.3.6.1.2.1.2.2.1.16.{i}", counter(out_oct, oo, int(oo*0.1))),
|
||||||
|
ln(f"1.3.6.1.2.1.2.2.1.17.{i}", counter(out_pkt, od, int(od*0.1))),
|
||||||
|
ln(f"1.3.6.1.2.1.2.2.1.19.{i}", counter(disc, 0, 1)),
|
||||||
|
ln(f"1.3.6.1.2.1.2.2.1.20.{i}", counter(err, 0, 1)),
|
||||||
|
]
|
||||||
|
|
||||||
|
cpu_lo = max(1, cpu_base - 10); cpu_hi = min(99, cpu_base + 20)
|
||||||
|
cpu_dev = max(3, cpu_base // 3)
|
||||||
|
lines += [
|
||||||
|
f"1.3.6.1.4.1.9.9.109.1.1.1.1.2.1|2|1",
|
||||||
|
ln("1.3.6.1.4.1.9.9.109.1.1.1.1.3.1", gauge(cpu_base, cpu_lo, cpu_hi, cpu_dev)),
|
||||||
|
ln("1.3.6.1.4.1.9.9.109.1.1.1.1.4.1", gauge(cpu_base, cpu_lo, cpu_hi, cpu_dev)),
|
||||||
|
ln("1.3.6.1.4.1.9.9.109.1.1.1.1.5.1", gauge(cpu_base, cpu_lo, cpu_hi, cpu_dev)),
|
||||||
|
ln("1.3.6.1.4.1.9.2.1.57.0", gauge(cpu_base, cpu_lo, cpu_hi, cpu_dev)),
|
||||||
|
ln("1.3.6.1.4.1.9.2.1.58.0", gauge(cpu_base, cpu_lo, cpu_hi, cpu_dev)),
|
||||||
|
f"1.3.6.1.4.1.9.9.48.1.1.1.2.1|4|Processor",
|
||||||
|
ln("1.3.6.1.4.1.9.9.48.1.1.1.5.1", gauge(mem_free, mem_free-5_000_000, mem_free+5_000_000, 2_000_000)),
|
||||||
|
ln("1.3.6.1.4.1.9.9.48.1.1.1.6.1", gauge(mem_used, mem_used-5_000_000, mem_used+5_000_000, 2_000_000)),
|
||||||
|
f"1.3.6.1.4.1.9.9.48.1.1.1.2.2|4|I/O",
|
||||||
|
ln("1.3.6.1.4.1.9.9.48.1.1.1.5.2", gauge(mem_free//4, mem_free//4-1_000_000, mem_free//4+1_000_000, 500_000)),
|
||||||
|
ln("1.3.6.1.4.1.9.9.48.1.1.1.6.2", gauge(mem_used//8, mem_used//8-500_000, mem_used//8+500_000, 250_000)),
|
||||||
|
]
|
||||||
|
return "\n".join(lines) + "\n"
|
||||||
|
|
||||||
|
for idx, (hostname, descr, sysoid, port) in enumerate(DEVICES):
|
||||||
|
ifaces = ROUTER_IFACES if "rtr" in hostname else (FW_IFACES if "fw" in hostname else SWITCH_IFACES)
|
||||||
|
content = make_snmprec(idx, hostname, descr, sysoid, ifaces)
|
||||||
|
out_dir = os.path.join(BASE_OUTPUT_DIR, f"port-{port}")
|
||||||
|
os.makedirs(out_dir, exist_ok=True)
|
||||||
|
with open(os.path.join(out_dir, "public.snmprec"), "w") as f:
|
||||||
|
f.write(content)
|
||||||
|
print(f" port-{port}/public.snmprec ({hostname}, {len(ifaces)} interfaces)")
|
||||||
|
|
||||||
|
print("Done.")
|
||||||
|
PYEOF
|
||||||
|
|
||||||
|
info "Generating device data files..."
|
||||||
|
python3 "${INSTALL_DIR}/generate_devices.py"
|
||||||
|
chown -R "${SNMPSIM_USER}:${SNMPSIM_USER}" "${INSTALL_DIR}/data"
|
||||||
|
ok "Device data files generated"
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
section "Step 5: Create start / stop scripts"
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
cat > "${INSTALL_DIR}/start-sim.sh" << EOF
|
||||||
|
#!/bin/bash
|
||||||
|
# =============================================================================
|
||||||
|
# Start 10 Cisco SNMP agents — all SNMPv2c, community: public
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
SNMPSIM_BIN="${SNMPSIM_BIN}"
|
||||||
|
BASE_DATA_DIR="${INSTALL_DIR}/data"
|
||||||
|
LOGFILE="${INSTALL_DIR}/logs/snmpsim.log"
|
||||||
|
PID_DIR="/var/run/snmpsim.commands.responder"
|
||||||
|
VM_IP="${VM_IP}"
|
||||||
|
|
||||||
|
declare -A DEVICES=(
|
||||||
|
[10000]="core-sw-01"
|
||||||
|
[10001]="core-sw-02"
|
||||||
|
[10002]="dist-sw-01"
|
||||||
|
[10003]="dist-sw-02"
|
||||||
|
[10004]="access-sw-01"
|
||||||
|
[10005]="access-sw-02"
|
||||||
|
[10006]="access-sw-03"
|
||||||
|
[10007]="rtr-01"
|
||||||
|
[10008]="rtr-02"
|
||||||
|
[10009]="fw-01"
|
||||||
|
)
|
||||||
|
|
||||||
|
echo "Starting 10 Cisco SNMP agents on \${VM_IP} (SNMPv2c, community: public)..."
|
||||||
|
> "\${LOGFILE}"
|
||||||
|
|
||||||
|
for PORT in \$(echo "\${!DEVICES[@]}" | tr ' ' '\n' | sort -n); do
|
||||||
|
NAME="\${DEVICES[\$PORT]}"
|
||||||
|
\${SNMPSIM_BIN} \\
|
||||||
|
--agent-udpv4-endpoint=\${VM_IP}:\${PORT} \\
|
||||||
|
--data-dir="\${BASE_DATA_DIR}/port-\${PORT}" \\
|
||||||
|
--process-user=${SNMPSIM_USER} \\
|
||||||
|
--process-group=${SNMPSIM_USER} \\
|
||||||
|
--pid-file="\${PID_DIR}/\${PORT}.pid" \\
|
||||||
|
--daemonize \\
|
||||||
|
--logging-method=file:\${LOGFILE}
|
||||||
|
echo " Started: \${NAME} on \${VM_IP}:\${PORT}"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Done. 10 agents running (SNMPv2c, community: public)"
|
||||||
|
echo "Verify: snmpwalk -v2c -c public \${VM_IP}:10000 1.3.6.1.2.1.1"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat > "${INSTALL_DIR}/stop-sim.sh" << 'EOF'
|
||||||
|
#!/bin/bash
|
||||||
|
PID_DIR="/var/run/snmpsim.commands.responder"
|
||||||
|
echo "Stopping snmpsim agents..."
|
||||||
|
STOPPED=0
|
||||||
|
for pidfile in "${PID_DIR}"/*.pid; do
|
||||||
|
[[ -f "$pidfile" ]] || continue
|
||||||
|
PID=$(cat "$pidfile" 2>/dev/null)
|
||||||
|
PORT=$(basename "$pidfile" .pid)
|
||||||
|
if kill "$PID" 2>/dev/null; then
|
||||||
|
echo " Stopped port $PORT (PID $PID)"
|
||||||
|
STOPPED=$((STOPPED+1))
|
||||||
|
fi
|
||||||
|
rm -f "$pidfile"
|
||||||
|
done
|
||||||
|
if [[ $STOPPED -eq 0 ]]; then
|
||||||
|
pkill -f snmpsim-command-responder 2>/dev/null && echo " Stopped via pkill" || echo " No snmpsim process found."
|
||||||
|
fi
|
||||||
|
echo "Done."
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat > "${INSTALL_DIR}/restart-sim.sh" << 'EOF'
|
||||||
|
#!/bin/bash
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
./stop-sim.sh
|
||||||
|
sleep 2
|
||||||
|
rm -rf /tmp/snmpsim/*
|
||||||
|
./start-sim.sh
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod +x "${INSTALL_DIR}"/{start-sim.sh,stop-sim.sh,restart-sim.sh}
|
||||||
|
ok "start-sim.sh, stop-sim.sh, restart-sim.sh created"
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
section "Step 6: Create trap generator"
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
cat > "${INSTALL_DIR}/trap-generator.sh" << EOF
|
||||||
|
#!/bin/bash
|
||||||
|
# =============================================================================
|
||||||
|
# trap-generator.sh
|
||||||
|
# Sends one random SNMP trap to the configured destination.
|
||||||
|
# Run manually or via cron.
|
||||||
|
#
|
||||||
|
# Usage: ./trap-generator.sh [--host <IP>] [--port <PORT>]
|
||||||
|
# Defaults to compiled-in values if no args given.
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
SEVONE_IP="\${1:-${TRAP_HOST}}"
|
||||||
|
SEVONE_PORT="\${2:-${TRAP_PORT}}"
|
||||||
|
COMMUNITY="public"
|
||||||
|
|
||||||
|
declare -A DEVICES
|
||||||
|
DEVICES["core-sw-01"]="${VM_IP}:10000:1.3.6.1.4.1.9.1.282"
|
||||||
|
DEVICES["core-sw-02"]="${VM_IP}:10001:1.3.6.1.4.1.9.1.282"
|
||||||
|
DEVICES["dist-sw-01"]="${VM_IP}:10002:1.3.6.1.4.1.9.1.659"
|
||||||
|
DEVICES["dist-sw-02"]="${VM_IP}:10003:1.3.6.1.4.1.9.1.659"
|
||||||
|
DEVICES["access-sw-01"]="${VM_IP}:10004:1.3.6.1.4.1.9.1.516"
|
||||||
|
DEVICES["access-sw-02"]="${VM_IP}:10005:1.3.6.1.4.1.9.1.516"
|
||||||
|
DEVICES["access-sw-03"]="${VM_IP}:10006:1.3.6.1.4.1.9.1.516"
|
||||||
|
DEVICES["rtr-01"]="${VM_IP}:10007:1.3.6.1.4.1.9.1.1861"
|
||||||
|
DEVICES["rtr-02"]="${VM_IP}:10008:1.3.6.1.4.1.9.1.1861"
|
||||||
|
DEVICES["fw-01"]="${VM_IP}:10009:1.3.6.1.4.1.9.1.1902"
|
||||||
|
|
||||||
|
SWITCH_IFACES=("GigabitEthernet0/1" "GigabitEthernet0/2" "GigabitEthernet0/3" "GigabitEthernet0/4" "GigabitEthernet0/5" "TenGigabitEthernet1/1" "TenGigabitEthernet1/2")
|
||||||
|
ROUTER_IFACES=("GigabitEthernet0/0/0" "GigabitEthernet0/0/1" "Serial0/1/0")
|
||||||
|
FW_IFACES=("GigabitEthernet0/0" "GigabitEthernet0/1" "GigabitEthernet0/2" "Management0/0")
|
||||||
|
|
||||||
|
random_element() { local a=("\$@"); echo "\${a[\$RANDOM % \${#a[@]}]}"; }
|
||||||
|
random_device() { local k=("\${!DEVICES[@]}"); echo "\${k[\$RANDOM % \${#k[@]}]}"; }
|
||||||
|
|
||||||
|
get_ifaces() {
|
||||||
|
case "\$1" in
|
||||||
|
rtr*) echo "\${ROUTER_IFACES[@]}" ;;
|
||||||
|
fw*) echo "\${FW_IFACES[@]}" ;;
|
||||||
|
*) echo "\${SWITCH_IFACES[@]}" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
send_linkDown() {
|
||||||
|
local dev="\$1"; local ifaces=(\$(get_ifaces "\$dev"))
|
||||||
|
local iface=\$(random_element "\${ifaces[@]}"); local idx=\$((RANDOM % \${#ifaces[@]} + 1))
|
||||||
|
echo "[\$(date '+%H:%M:%S')] linkDown | \$dev | \$iface"
|
||||||
|
snmptrap -v2c -c "\$COMMUNITY" "\$SEVONE_IP:\$SEVONE_PORT" "" 1.3.6.1.6.3.1.1.5.3 \\
|
||||||
|
1.3.6.1.2.1.2.2.1.1.\$idx i \$idx 1.3.6.1.2.1.2.2.1.2.\$idx s "\$iface" \\
|
||||||
|
1.3.6.1.2.1.2.2.1.7.\$idx i 2 1.3.6.1.2.1.2.2.1.8.\$idx i 2
|
||||||
|
}
|
||||||
|
|
||||||
|
send_linkUp() {
|
||||||
|
local dev="\$1"; local ifaces=(\$(get_ifaces "\$dev"))
|
||||||
|
local iface=\$(random_element "\${ifaces[@]}"); local idx=\$((RANDOM % \${#ifaces[@]} + 1))
|
||||||
|
echo "[\$(date '+%H:%M:%S')] linkUp | \$dev | \$iface"
|
||||||
|
snmptrap -v2c -c "\$COMMUNITY" "\$SEVONE_IP:\$SEVONE_PORT" "" 1.3.6.1.6.3.1.1.5.4 \\
|
||||||
|
1.3.6.1.2.1.2.2.1.1.\$idx i \$idx 1.3.6.1.2.1.2.2.1.2.\$idx s "\$iface" \\
|
||||||
|
1.3.6.1.2.1.2.2.1.7.\$idx i 1 1.3.6.1.2.1.2.2.1.8.\$idx i 1
|
||||||
|
}
|
||||||
|
|
||||||
|
send_coldStart() {
|
||||||
|
echo "[\$(date '+%H:%M:%S')] coldStart | \$1"
|
||||||
|
snmptrap -v2c -c "\$COMMUNITY" "\$SEVONE_IP:\$SEVONE_PORT" "" 1.3.6.1.6.3.1.1.5.1
|
||||||
|
}
|
||||||
|
|
||||||
|
send_warmStart() {
|
||||||
|
echo "[\$(date '+%H:%M:%S')] warmStart | \$1"
|
||||||
|
snmptrap -v2c -c "\$COMMUNITY" "\$SEVONE_IP:\$SEVONE_PORT" "" 1.3.6.1.6.3.1.1.5.2
|
||||||
|
}
|
||||||
|
|
||||||
|
send_ospfNbrStateChange() {
|
||||||
|
[[ "\$1" != rtr* ]] && return
|
||||||
|
local peer="10.\$((RANDOM%255)).\$((RANDOM%255)).\$((RANDOM%255))"
|
||||||
|
local state=\$((RANDOM%8+1))
|
||||||
|
echo "[\$(date '+%H:%M:%S')] ospfNbrStateChange| \$1 | peer \$peer state \$state"
|
||||||
|
snmptrap -v2c -c "\$COMMUNITY" "\$SEVONE_IP:\$SEVONE_PORT" "" 1.3.6.1.4.1.9.10.99.0.1 \\
|
||||||
|
1.3.6.1.2.1.14.10.1.1.\$peer a "\$peer" 1.3.6.1.2.1.14.10.1.6.\$peer i \$state \\
|
||||||
|
1.3.6.1.2.1.14.4.1.2.0 s "0.0.0.0"
|
||||||
|
}
|
||||||
|
|
||||||
|
send_bgpEstablished() {
|
||||||
|
[[ "\$1" != rtr* ]] && return
|
||||||
|
local peer="192.168.\$((RANDOM%255)).\$((RANDOM%255))"
|
||||||
|
local as=\$((RANDOM%65000+1000))
|
||||||
|
echo "[\$(date '+%H:%M:%S')] bgpEstablished | \$1 | peer \$peer AS\$as"
|
||||||
|
snmptrap -v2c -c "\$COMMUNITY" "\$SEVONE_IP:\$SEVONE_PORT" "" 1.3.6.1.2.1.15.7.1 \\
|
||||||
|
1.3.6.1.2.1.15.3.1.7.\$peer i 6 1.3.6.1.2.1.15.3.1.9.\$peer i \$as
|
||||||
|
}
|
||||||
|
|
||||||
|
send_bgpBackwardTransition() {
|
||||||
|
[[ "\$1" != rtr* ]] && return
|
||||||
|
local peer="192.168.\$((RANDOM%255)).\$((RANDOM%255))"
|
||||||
|
local as=\$((RANDOM%65000+1000)); local state=\$((RANDOM%5+1))
|
||||||
|
echo "[\$(date '+%H:%M:%S')] bgpBackward | \$1 | peer \$peer state \$state"
|
||||||
|
snmptrap -v2c -c "\$COMMUNITY" "\$SEVONE_IP:\$SEVONE_PORT" "" 1.3.6.1.2.1.15.7.2 \\
|
||||||
|
1.3.6.1.2.1.15.3.1.7.\$peer i \$state 1.3.6.1.2.1.15.3.1.9.\$peer i \$as
|
||||||
|
}
|
||||||
|
|
||||||
|
send_cpuThreshold() {
|
||||||
|
local cpu=\$((RANDOM%40+60))
|
||||||
|
echo "[\$(date '+%H:%M:%S')] cpuThreshold | \$1 | CPU \${cpu}%"
|
||||||
|
snmptrap -v2c -c "\$COMMUNITY" "\$SEVONE_IP:\$SEVONE_PORT" "" 1.3.6.1.4.1.9.9.109.0.1 \\
|
||||||
|
1.3.6.1.4.1.9.9.109.1.1.1.1.3.1 i \$cpu \\
|
||||||
|
1.3.6.1.4.1.9.9.109.1.1.1.1.4.1 i \$((cpu-RANDOM%10)) \\
|
||||||
|
1.3.6.1.4.1.9.9.109.1.1.1.1.5.1 i \$((cpu-RANDOM%15))
|
||||||
|
}
|
||||||
|
|
||||||
|
TRAP_TYPES=(linkDown linkDown linkDown linkUp linkUp linkUp coldStart warmStart
|
||||||
|
ospfNbrStateChange ospfNbrStateChange bgpEstablished
|
||||||
|
bgpBackwardTransition cpuThreshold)
|
||||||
|
|
||||||
|
trap_type=\$(random_element "\${TRAP_TYPES[@]}")
|
||||||
|
device=\$(random_device)
|
||||||
|
|
||||||
|
echo "--- \$(date '+%Y-%m-%d %H:%M:%S') | \$trap_type from \$device -> \$SEVONE_IP:\$SEVONE_PORT ---"
|
||||||
|
case "\$trap_type" in
|
||||||
|
linkDown) send_linkDown "\$device" ;;
|
||||||
|
linkUp) send_linkUp "\$device" ;;
|
||||||
|
coldStart) send_coldStart "\$device" ;;
|
||||||
|
warmStart) send_warmStart "\$device" ;;
|
||||||
|
ospfNbrStateChange) send_ospfNbrStateChange "\$device" ;;
|
||||||
|
bgpEstablished) send_bgpEstablished "\$device" ;;
|
||||||
|
bgpBackwardTransition) send_bgpBackwardTransition "\$device" ;;
|
||||||
|
cpuThreshold) send_cpuThreshold "\$device" ;;
|
||||||
|
esac
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod +x "${INSTALL_DIR}/trap-generator.sh"
|
||||||
|
ok "trap-generator.sh created"
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
section "Step 7: Build and install nflow-generator"
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
NFLOW_BIN="${INSTALL_DIR}/nflow-generator"
|
||||||
|
|
||||||
|
if [[ -f "$NFLOW_BIN" ]]; then
|
||||||
|
ok "nflow-generator already present — skipping build"
|
||||||
|
else
|
||||||
|
info "Cloning and building nflow-generator..."
|
||||||
|
TMPDIR=$(mktemp -d)
|
||||||
|
git clone --quiet https://github.com/nerdalert/nflow-generator.git "$TMPDIR/nflow-generator"
|
||||||
|
cd "$TMPDIR/nflow-generator"
|
||||||
|
go build -o "$NFLOW_BIN" .
|
||||||
|
cd /
|
||||||
|
rm -rf "$TMPDIR"
|
||||||
|
ok "nflow-generator built: $NFLOW_BIN"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
section "Step 8: Create systemd services"
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
# NetFlow systemd service
|
||||||
|
cat > /etc/systemd/system/snmpsim-netflow.service << EOF
|
||||||
|
[Unit]
|
||||||
|
Description=SevOne Lab NetFlow Generator
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=${INSTALL_DIR}/nflow-generator -t ${NETFLOW_HOST} -p ${NETFLOW_PORT}
|
||||||
|
Restart=always
|
||||||
|
RestartSec=5
|
||||||
|
StandardOutput=journal
|
||||||
|
StandardError=journal
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Trap generator systemd timer (every 5 minutes)
|
||||||
|
cat > /etc/systemd/system/snmpsim-traps.service << EOF
|
||||||
|
[Unit]
|
||||||
|
Description=SevOne Lab Trap Generator (single run)
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
ExecStart=${INSTALL_DIR}/trap-generator.sh ${TRAP_HOST} ${TRAP_PORT}
|
||||||
|
StandardOutput=journal
|
||||||
|
StandardError=journal
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat > /etc/systemd/system/snmpsim-traps.timer << EOF
|
||||||
|
[Unit]
|
||||||
|
Description=SevOne Lab Trap Generator — every 5 minutes
|
||||||
|
|
||||||
|
[Timer]
|
||||||
|
OnBootSec=60
|
||||||
|
OnUnitActiveSec=5min
|
||||||
|
Unit=snmpsim-traps.service
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=timers.target
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# SNMP simulator systemd service
|
||||||
|
# Type=oneshot + RemainAfterExit=yes is correct for a script that launches
|
||||||
|
# background daemons and exits. HOME must be set so snmpsim can find its
|
||||||
|
# variation modules path (~/.snmpsim/variation).
|
||||||
|
cat > /etc/systemd/system/snmpsim-agents.service << EOF
|
||||||
|
[Unit]
|
||||||
|
Description=SevOne Lab SNMP Simulator (10 Cisco agents)
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
RemainAfterExit=yes
|
||||||
|
Environment=HOME=/root
|
||||||
|
ExecStart=${INSTALL_DIR}/start-sim.sh
|
||||||
|
ExecStop=${INSTALL_DIR}/stop-sim.sh
|
||||||
|
ExecReload=${INSTALL_DIR}/restart-sim.sh
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl enable --now snmpsim-agents.service
|
||||||
|
systemctl enable --now snmpsim-netflow.service
|
||||||
|
systemctl enable --now snmpsim-traps.timer
|
||||||
|
|
||||||
|
ok "systemd services created, enabled, and started:"
|
||||||
|
ok " snmpsim-agents.service (SNMP -> ${VM_IP}:10000-10009, community: public)"
|
||||||
|
ok " snmpsim-netflow.service (NetFlow -> ${NETFLOW_HOST}:${NETFLOW_PORT})"
|
||||||
|
ok " snmpsim-traps.timer (Traps -> ${TRAP_HOST}:${TRAP_PORT} every 5 min)"
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
section "Step 9: Fix ownership"
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
chown -R "${SNMPSIM_USER}:${SNMPSIM_USER}" "${INSTALL_DIR}"
|
||||||
|
chown root:root "${INSTALL_DIR}/start-sim.sh" "${INSTALL_DIR}/stop-sim.sh" "${INSTALL_DIR}/restart-sim.sh"
|
||||||
|
chmod +x "${INSTALL_DIR}/start-sim.sh" "${INSTALL_DIR}/stop-sim.sh" "${INSTALL_DIR}/restart-sim.sh"
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
section "Step 10: Verify installation"
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
sleep 3
|
||||||
|
PASS=0; FAIL=0
|
||||||
|
|
||||||
|
check() {
|
||||||
|
local desc="$1"; local cmd="$2"
|
||||||
|
if eval "$cmd" &>/dev/null; then
|
||||||
|
ok "$desc"
|
||||||
|
PASS=$((PASS+1))
|
||||||
|
else
|
||||||
|
error "$desc"
|
||||||
|
FAIL=$((FAIL+1))
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
check "snmpsim-agents service active" "systemctl is-active --quiet snmpsim-agents"
|
||||||
|
check "Port 10000 bound (core-sw-01)" "ss -ulnp | grep -q ':10000'"
|
||||||
|
check "Port 10007 bound (rtr-01)" "ss -ulnp | grep -q ':10007'"
|
||||||
|
check "SNMPv2c response (port 10000)" "snmpget -v2c -c public ${VM_IP}:10000 1.3.6.1.2.1.1.5.0 2>/dev/null"
|
||||||
|
check "SNMPv2c response (port 10005)" "snmpget -v2c -c public ${VM_IP}:10005 1.3.6.1.2.1.1.5.0 2>/dev/null"
|
||||||
|
check "SNMPv2c response (port 10009)" "snmpget -v2c -c public ${VM_IP}:10009 1.3.6.1.2.1.1.5.0 2>/dev/null"
|
||||||
|
check "nflow-generator service active" "systemctl is-active --quiet snmpsim-netflow"
|
||||||
|
check "trap timer active" "systemctl is-active --quiet snmpsim-traps.timer"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo -e "${BLUE}═══════════════════════════════════════════════════════${NC}"
|
||||||
|
echo -e " Checks passed: ${GREEN}${PASS}${NC} Checks failed: ${RED}${FAIL}${NC}"
|
||||||
|
echo -e "${BLUE}═══════════════════════════════════════════════════════${NC}"
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
# Final summary
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
echo ""
|
||||||
|
echo -e "${BLUE}╔══════════════════════════════════════════════════════════╗${NC}"
|
||||||
|
echo -e "${BLUE}║ Installation complete ║${NC}"
|
||||||
|
echo -e "${BLUE}╚══════════════════════════════════════════════════════════╝${NC}"
|
||||||
|
echo ""
|
||||||
|
echo -e " Install directory : ${CYAN}${INSTALL_DIR}${NC}"
|
||||||
|
echo -e " VM IP : ${CYAN}${VM_IP}${NC}"
|
||||||
|
echo -e " Trap destination : ${CYAN}${TRAP_HOST}:${TRAP_PORT}${NC}"
|
||||||
|
echo -e " NetFlow dest : ${CYAN}${NETFLOW_HOST}:${NETFLOW_PORT}${NC}"
|
||||||
|
echo ""
|
||||||
|
echo -e " SNMP devices : ${CYAN}${VM_IP}:10000 - ${VM_IP}:10009${NC}"
|
||||||
|
echo -e " SNMP version : ${CYAN}v2c${NC}"
|
||||||
|
echo -e " Community string : ${CYAN}public${NC}"
|
||||||
|
echo ""
|
||||||
|
echo -e " ${YELLOW}Add each device to SevOne:${NC}"
|
||||||
|
echo -e " IP: ${VM_IP}, SNMP Version: v2c, Community: public, Port: 10000 through 10009"
|
||||||
|
echo ""
|
||||||
|
echo -e " ${YELLOW}Useful commands:${NC}"
|
||||||
|
echo -e " ${INSTALL_DIR}/start-sim.sh"
|
||||||
|
echo -e " ${INSTALL_DIR}/stop-sim.sh"
|
||||||
|
echo -e " ${INSTALL_DIR}/restart-sim.sh"
|
||||||
|
echo -e " ${INSTALL_DIR}/trap-generator.sh # send one trap now"
|
||||||
|
echo -e " systemctl status snmpsim-netflow"
|
||||||
|
echo -e " systemctl status snmpsim-traps.timer"
|
||||||
|
echo -e " tail -f ${INSTALL_DIR}/logs/snmpsim.log"
|
||||||
|
echo ""
|
||||||
BIN
install-snmpsim-lab.sh:Zone.Identifier
Normal file
BIN
install-snmpsim-lab.sh:Zone.Identifier
Normal file
Binary file not shown.
232
trap-generator.sh
Normal file
232
trap-generator.sh
Normal file
@ -0,0 +1,232 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# =============================================================================
|
||||||
|
# trap-generator.sh
|
||||||
|
# Sends random SNMP traps to a SevOne collector (UDP 162)
|
||||||
|
# Simulates a mixed Cisco environment: link traps, coldStart, warmStart,
|
||||||
|
# OSPF neighbor changes, BGP state changes, and CPU threshold alerts.
|
||||||
|
#
|
||||||
|
# Usage: ./trap-generator.sh <SevOne_IP>
|
||||||
|
# or run continuously: watch -n 30 ./trap-generator.sh <SevOne_IP>
|
||||||
|
# or via cron: */5 * * * * /opt/snmpsim-lab/trap-generator.sh <SevOne_IP>
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
SEVONE_IP="${1:-10.0.0.1}"
|
||||||
|
SEVONE_PORT="162"
|
||||||
|
COMMUNITY="public"
|
||||||
|
|
||||||
|
# The 10 simulated devices (hostname -> IP:port -> sysObjectID)
|
||||||
|
# We spoof the agent address so SevOne sees the trap as coming from each device
|
||||||
|
declare -A DEVICES
|
||||||
|
DEVICES["core-sw-01"]="9.60.154.118:10000:1.3.6.1.4.1.9.1.282"
|
||||||
|
DEVICES["core-sw-02"]="9.60.154.118:10001:1.3.6.1.4.1.9.1.282"
|
||||||
|
DEVICES["dist-sw-01"]="9.60.154.118:10002:1.3.6.1.4.1.9.1.659"
|
||||||
|
DEVICES["dist-sw-02"]="9.60.154.118:10003:1.3.6.1.4.1.9.1.659"
|
||||||
|
DEVICES["access-sw-01"]="9.60.154.118:10004:1.3.6.1.4.1.9.1.516"
|
||||||
|
DEVICES["access-sw-02"]="9.60.154.118:10005:1.3.6.1.4.1.9.1.516"
|
||||||
|
DEVICES["access-sw-03"]="9.60.154.118:10006:1.3.6.1.4.1.9.1.516"
|
||||||
|
DEVICES["rtr-01"]="9.60.154.118:10007:1.3.6.1.4.1.9.1.1861"
|
||||||
|
DEVICES["rtr-02"]="9.60.154.118:10008:1.3.6.1.4.1.9.1.1861"
|
||||||
|
DEVICES["fw-01"]="9.60.154.118:10009:1.3.6.1.4.1.9.1.1902"
|
||||||
|
|
||||||
|
# Interface names per device type
|
||||||
|
SWITCH_IFACES=("GigabitEthernet0/1" "GigabitEthernet0/2" "GigabitEthernet0/3" "GigabitEthernet0/4" "GigabitEthernet0/5" "TenGigabitEthernet1/1" "TenGigabitEthernet1/2")
|
||||||
|
ROUTER_IFACES=("GigabitEthernet0/0/0" "GigabitEthernet0/0/1" "Serial0/1/0")
|
||||||
|
FW_IFACES=("GigabitEthernet0/0" "GigabitEthernet0/1" "GigabitEthernet0/2" "Management0/0")
|
||||||
|
|
||||||
|
# Pick a random element from an array
|
||||||
|
random_element() {
|
||||||
|
local arr=("$@")
|
||||||
|
echo "${arr[$RANDOM % ${#arr[@]}]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Pick a random device name
|
||||||
|
random_device() {
|
||||||
|
local keys=("${!DEVICES[@]}")
|
||||||
|
echo "${keys[$RANDOM % ${#keys[@]}]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get interface list for a device
|
||||||
|
get_ifaces() {
|
||||||
|
local device="$1"
|
||||||
|
if [[ "$device" == rtr* ]]; then
|
||||||
|
echo "${ROUTER_IFACES[@]}"
|
||||||
|
elif [[ "$device" == fw* ]]; then
|
||||||
|
echo "${FW_IFACES[@]}"
|
||||||
|
else
|
||||||
|
echo "${SWITCH_IFACES[@]}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# -------------------------------------------------------
|
||||||
|
# TRAP SENDERS
|
||||||
|
# Each function sends one specific trap type.
|
||||||
|
# snmptrap syntax:
|
||||||
|
# snmptrap -v2c -c <community> <target> <uptime> <trap-oid> [varbinds...]
|
||||||
|
# -------------------------------------------------------
|
||||||
|
|
||||||
|
send_linkDown() {
|
||||||
|
local device="$1"
|
||||||
|
local info="${DEVICES[$device]}"
|
||||||
|
local agent_ip=$(echo "$info" | cut -d: -f1)
|
||||||
|
local ifaces=($(get_ifaces "$device"))
|
||||||
|
local iface=$(random_element "${ifaces[@]}")
|
||||||
|
local ifindex=$((RANDOM % ${#ifaces[@]} + 1))
|
||||||
|
local uptime=$((RANDOM % 9000000 + 100000))
|
||||||
|
|
||||||
|
echo "[$(date '+%H:%M:%S')] linkDown | $device | $iface (ifIndex $ifindex)"
|
||||||
|
|
||||||
|
snmptrap -v2c -c "$COMMUNITY" "$SEVONE_IP:$SEVONE_PORT" \
|
||||||
|
"" \
|
||||||
|
1.3.6.1.6.3.1.1.5.3 \
|
||||||
|
1.3.6.1.2.1.2.2.1.1.$ifindex i $ifindex \
|
||||||
|
1.3.6.1.2.1.2.2.1.2.$ifindex s "$iface" \
|
||||||
|
1.3.6.1.2.1.2.2.1.7.$ifindex i 2 \
|
||||||
|
1.3.6.1.2.1.2.2.1.8.$ifindex i 2
|
||||||
|
}
|
||||||
|
|
||||||
|
send_linkUp() {
|
||||||
|
local device="$1"
|
||||||
|
local info="${DEVICES[$device]}"
|
||||||
|
local agent_ip=$(echo "$info" | cut -d: -f1)
|
||||||
|
local ifaces=($(get_ifaces "$device"))
|
||||||
|
local iface=$(random_element "${ifaces[@]}")
|
||||||
|
local ifindex=$((RANDOM % ${#ifaces[@]} + 1))
|
||||||
|
|
||||||
|
echo "[$(date '+%H:%M:%S')] linkUp | $device | $iface (ifIndex $ifindex)"
|
||||||
|
|
||||||
|
snmptrap -v2c -c "$COMMUNITY" "$SEVONE_IP:$SEVONE_PORT" \
|
||||||
|
"" \
|
||||||
|
1.3.6.1.6.3.1.1.5.4 \
|
||||||
|
1.3.6.1.2.1.2.2.1.1.$ifindex i $ifindex \
|
||||||
|
1.3.6.1.2.1.2.2.1.2.$ifindex s "$iface" \
|
||||||
|
1.3.6.1.2.1.2.2.1.7.$ifindex i 1 \
|
||||||
|
1.3.6.1.2.1.2.2.1.8.$ifindex i 1
|
||||||
|
}
|
||||||
|
|
||||||
|
send_coldStart() {
|
||||||
|
local device="$1"
|
||||||
|
|
||||||
|
echo "[$(date '+%H:%M:%S')] coldStart | $device"
|
||||||
|
|
||||||
|
snmptrap -v2c -c "$COMMUNITY" "$SEVONE_IP:$SEVONE_PORT" \
|
||||||
|
"" \
|
||||||
|
1.3.6.1.6.3.1.1.5.1
|
||||||
|
}
|
||||||
|
|
||||||
|
send_warmStart() {
|
||||||
|
local device="$1"
|
||||||
|
|
||||||
|
echo "[$(date '+%H:%M:%S')] warmStart | $device"
|
||||||
|
|
||||||
|
snmptrap -v2c -c "$COMMUNITY" "$SEVONE_IP:$SEVONE_PORT" \
|
||||||
|
"" \
|
||||||
|
1.3.6.1.6.3.1.1.5.2
|
||||||
|
}
|
||||||
|
|
||||||
|
send_ospfNbrStateChange() {
|
||||||
|
local device="$1"
|
||||||
|
# Only routers run OSPF
|
||||||
|
if [[ "$device" != rtr* ]]; then return; fi
|
||||||
|
|
||||||
|
local neighbor="10.$((RANDOM % 255)).$((RANDOM % 255)).$((RANDOM % 255))"
|
||||||
|
# OSPF states: 1=down 2=attempt 3=init 4=twoWay 5=exchangeStart 6=exchange 7=loading 8=full
|
||||||
|
local state=$((RANDOM % 8 + 1))
|
||||||
|
local state_names=("" "down" "attempt" "init" "twoWay" "exchangeStart" "exchange" "loading" "full")
|
||||||
|
|
||||||
|
echo "[$(date '+%H:%M:%S')] ospfNbrStateChange | $device | neighbor $neighbor -> ${state_names[$state]}"
|
||||||
|
|
||||||
|
snmptrap -v2c -c "$COMMUNITY" "$SEVONE_IP:$SEVONE_PORT" \
|
||||||
|
"" \
|
||||||
|
1.3.6.1.4.1.9.10.99.0.1 \
|
||||||
|
1.3.6.1.2.1.14.10.1.1.$neighbor a "$neighbor" \
|
||||||
|
1.3.6.1.2.1.14.10.1.6.$neighbor i $state \
|
||||||
|
1.3.6.1.2.1.14.4.1.2.0 s "0.0.0.0"
|
||||||
|
}
|
||||||
|
|
||||||
|
send_bgpEstablished() {
|
||||||
|
local device="$1"
|
||||||
|
# Only routers run BGP
|
||||||
|
if [[ "$device" != rtr* ]]; then return; fi
|
||||||
|
|
||||||
|
local peer="192.168.$((RANDOM % 255)).$((RANDOM % 255))"
|
||||||
|
local remote_as=$((RANDOM % 65000 + 1000))
|
||||||
|
|
||||||
|
echo "[$(date '+%H:%M:%S')] bgpEstablished | $device | peer $peer AS$remote_as"
|
||||||
|
|
||||||
|
snmptrap -v2c -c "$COMMUNITY" "$SEVONE_IP:$SEVONE_PORT" \
|
||||||
|
"" \
|
||||||
|
1.3.6.1.2.1.15.7.1 \
|
||||||
|
1.3.6.1.2.1.15.3.1.7.$peer i 6 \
|
||||||
|
1.3.6.1.2.1.15.3.1.9.$peer i $remote_as
|
||||||
|
}
|
||||||
|
|
||||||
|
send_bgpBackwardTransition() {
|
||||||
|
local device="$1"
|
||||||
|
if [[ "$device" != rtr* ]]; then return; fi
|
||||||
|
|
||||||
|
local peer="192.168.$((RANDOM % 255)).$((RANDOM % 255))"
|
||||||
|
local remote_as=$((RANDOM % 65000 + 1000))
|
||||||
|
# States: 1=idle 2=connect 3=active 4=openSent 5=openConfirm 6=established
|
||||||
|
local state=$((RANDOM % 5 + 1))
|
||||||
|
|
||||||
|
echo "[$(date '+%H:%M:%S')] bgpBackwardTransition | $device | peer $peer -> state $state"
|
||||||
|
|
||||||
|
snmptrap -v2c -c "$COMMUNITY" "$SEVONE_IP:$SEVONE_PORT" \
|
||||||
|
"" \
|
||||||
|
1.3.6.1.2.1.15.7.2 \
|
||||||
|
1.3.6.1.2.1.15.3.1.7.$peer i $state \
|
||||||
|
1.3.6.1.2.1.15.3.1.9.$peer i $remote_as
|
||||||
|
}
|
||||||
|
|
||||||
|
send_cpuThreshold() {
|
||||||
|
local device="$1"
|
||||||
|
local cpu=$((RANDOM % 40 + 60)) # 60-99%
|
||||||
|
|
||||||
|
echo "[$(date '+%H:%M:%S')] cpuThreshold | $device | CPU ${cpu}%"
|
||||||
|
|
||||||
|
snmptrap -v2c -c "$COMMUNITY" "$SEVONE_IP:$SEVONE_PORT" \
|
||||||
|
"" \
|
||||||
|
1.3.6.1.4.1.9.9.109.0.1 \
|
||||||
|
1.3.6.1.4.1.9.9.109.1.1.1.1.3.1 i $cpu \
|
||||||
|
1.3.6.1.4.1.9.9.109.1.1.1.1.4.1 i $((cpu - RANDOM % 10)) \
|
||||||
|
1.3.6.1.4.1.9.9.109.1.1.1.1.5.1 i $((cpu - RANDOM % 15))
|
||||||
|
}
|
||||||
|
|
||||||
|
# -------------------------------------------------------
|
||||||
|
# MAIN - pick random trap type and random device
|
||||||
|
# -------------------------------------------------------
|
||||||
|
|
||||||
|
# Weighted trap type selection
|
||||||
|
# Link traps are most common in real networks
|
||||||
|
TRAP_TYPES=(
|
||||||
|
"linkDown"
|
||||||
|
"linkDown"
|
||||||
|
"linkDown"
|
||||||
|
"linkUp"
|
||||||
|
"linkUp"
|
||||||
|
"linkUp"
|
||||||
|
"coldStart"
|
||||||
|
"warmStart"
|
||||||
|
"ospfNbrStateChange"
|
||||||
|
"ospfNbrStateChange"
|
||||||
|
"bgpEstablished"
|
||||||
|
"bgpBackwardTransition"
|
||||||
|
"cpuThreshold"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Pick random trap type and device
|
||||||
|
trap_type=$(random_element "${TRAP_TYPES[@]}")
|
||||||
|
device=$(random_device)
|
||||||
|
|
||||||
|
echo "--- Sending trap: $trap_type from $device to $SEVONE_IP:$SEVONE_PORT ---"
|
||||||
|
|
||||||
|
case "$trap_type" in
|
||||||
|
linkDown) send_linkDown "$device" ;;
|
||||||
|
linkUp) send_linkUp "$device" ;;
|
||||||
|
coldStart) send_coldStart "$device" ;;
|
||||||
|
warmStart) send_warmStart "$device" ;;
|
||||||
|
ospfNbrStateChange) send_ospfNbrStateChange "$device" ;;
|
||||||
|
bgpEstablished) send_bgpEstablished "$device" ;;
|
||||||
|
bgpBackwardTransition) send_bgpBackwardTransition "$device" ;;
|
||||||
|
cpuThreshold) send_cpuThreshold "$device" ;;
|
||||||
|
esac
|
||||||
BIN
trap-generator.sh:Zone.Identifier
Normal file
BIN
trap-generator.sh:Zone.Identifier
Normal file
Binary file not shown.
288
uninstall-snmpsim-lab.sh
Normal file
288
uninstall-snmpsim-lab.sh
Normal file
@ -0,0 +1,288 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# =============================================================================
|
||||||
|
# uninstall-snmpsim-lab.sh
|
||||||
|
#
|
||||||
|
# Completely removes the SevOne SNMP Simulation Lab.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# sudo ./uninstall-snmpsim-lab.sh [OPTIONS]
|
||||||
|
#
|
||||||
|
# Options:
|
||||||
|
# --yes Skip confirmation prompt
|
||||||
|
# --keep-pip Keep the snmpsim pip package installed
|
||||||
|
# --keep-user Keep the snmpsim system user
|
||||||
|
# -h, --help Show this help
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
INSTALL_DIR="/opt/snmpsim"
|
||||||
|
SNMPSIM_USER="snmpsim"
|
||||||
|
PID_DIR="/var/run/snmpsim.commands.responder"
|
||||||
|
CACHE_DIR="/tmp/snmpsim"
|
||||||
|
|
||||||
|
SERVICES=(
|
||||||
|
"snmpsim-agents.service"
|
||||||
|
"snmpsim-netflow.service"
|
||||||
|
"snmpsim-traps.timer"
|
||||||
|
"snmpsim-traps.service"
|
||||||
|
)
|
||||||
|
|
||||||
|
SERVICE_FILES=(
|
||||||
|
"/etc/systemd/system/snmpsim-agents.service"
|
||||||
|
"/etc/systemd/system/snmpsim-netflow.service"
|
||||||
|
"/etc/systemd/system/snmpsim-traps.service"
|
||||||
|
"/etc/systemd/system/snmpsim-traps.timer"
|
||||||
|
)
|
||||||
|
|
||||||
|
# ── Colours ───────────────────────────────────────────────────────────────────
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
CYAN='\033[0;36m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
info() { echo -e "${CYAN}[INFO]${NC} $*"; }
|
||||||
|
ok() { echo -e "${GREEN}[OK]${NC} $*"; }
|
||||||
|
skip() { echo -e "${YELLOW}[SKIP]${NC} $*"; }
|
||||||
|
section() { echo -e "\n${BLUE}══════════════════════════════════════════${NC}";
|
||||||
|
echo -e "${BLUE} $*${NC}";
|
||||||
|
echo -e "${BLUE}══════════════════════════════════════════${NC}"; }
|
||||||
|
|
||||||
|
# ── Must run as root ──────────────────────────────────────────────────────────
|
||||||
|
if [[ $EUID -ne 0 ]]; then
|
||||||
|
echo -e "${RED}[ERROR]${NC} This script must be run as root (sudo)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── Usage ─────────────────────────────────────────────────────────────────────
|
||||||
|
usage() {
|
||||||
|
cat << EOF
|
||||||
|
|
||||||
|
Usage: $(basename "$0") [OPTIONS]
|
||||||
|
|
||||||
|
OPTIONS:
|
||||||
|
--yes Skip confirmation prompt
|
||||||
|
--keep-pip Keep the snmpsim pip package installed
|
||||||
|
--keep-user Keep the snmpsim system user
|
||||||
|
-h, --help Show this help
|
||||||
|
|
||||||
|
EXAMPLES:
|
||||||
|
sudo $(basename "$0") # Full uninstall with prompt
|
||||||
|
sudo $(basename "$0") --yes # Full uninstall, no prompt
|
||||||
|
sudo $(basename "$0") --keep-pip --keep-user # Remove lab files only
|
||||||
|
|
||||||
|
EOF
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Parse arguments ───────────────────────────────────────────────────────────
|
||||||
|
SKIP_CONFIRM=0
|
||||||
|
KEEP_PIP=0
|
||||||
|
KEEP_USER=0
|
||||||
|
|
||||||
|
for arg in "$@"; do
|
||||||
|
case "$arg" in
|
||||||
|
--yes|-y) SKIP_CONFIRM=1 ;;
|
||||||
|
--keep-pip) KEEP_PIP=1 ;;
|
||||||
|
--keep-user) KEEP_USER=1 ;;
|
||||||
|
-h|--help) usage ;;
|
||||||
|
*) echo -e "${RED}[ERROR]${NC} Unknown option: $arg"; usage ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# ── Confirmation ──────────────────────────────────────────────────────────────
|
||||||
|
echo ""
|
||||||
|
echo -e "${RED}╔══════════════════════════════════════════════════╗${NC}"
|
||||||
|
echo -e "${RED}║ SevOne SNMP Lab Uninstaller ║${NC}"
|
||||||
|
echo -e "${RED}╚══════════════════════════════════════════════════╝${NC}"
|
||||||
|
echo ""
|
||||||
|
echo -e " Will remove:"
|
||||||
|
echo -e " ${CYAN}${INSTALL_DIR}/${NC} (all data, scripts, binaries)"
|
||||||
|
echo -e " ${CYAN}systemd services${NC} (snmpsim-agents, netflow, traps)"
|
||||||
|
echo -e " ${CYAN}${PID_DIR}/${NC}"
|
||||||
|
echo -e " ${CYAN}${CACHE_DIR}/${NC}"
|
||||||
|
|
||||||
|
if [[ $KEEP_PIP -eq 0 ]]; then
|
||||||
|
echo -e " ${CYAN}snmpsim pip package${NC}"
|
||||||
|
else
|
||||||
|
echo -e " ${YELLOW}snmpsim pip package${NC} (keeping -- --keep-pip)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $KEEP_USER -eq 0 ]]; then
|
||||||
|
echo -e " ${CYAN}snmpsim system user${NC}"
|
||||||
|
else
|
||||||
|
echo -e " ${YELLOW}snmpsim system user${NC} (keeping -- --keep-user)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if [[ $SKIP_CONFIRM -eq 0 ]]; then
|
||||||
|
read -rp "Are you sure you want to uninstall? [y/N] " CONFIRM
|
||||||
|
[[ "$CONFIRM" =~ ^[Yy]$ ]] || { echo "Aborted."; exit 0; }
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
section "Step 1: Stop and disable systemd services"
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
for svc in "${SERVICES[@]}"; do
|
||||||
|
if systemctl is-active --quiet "$svc" 2>/dev/null; then
|
||||||
|
systemctl stop "$svc"
|
||||||
|
ok "Stopped: $svc"
|
||||||
|
else
|
||||||
|
skip "Not running: $svc"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if systemctl is-enabled --quiet "$svc" 2>/dev/null; then
|
||||||
|
systemctl disable "$svc"
|
||||||
|
ok "Disabled: $svc"
|
||||||
|
else
|
||||||
|
skip "Not enabled: $svc"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
section "Step 2: Kill any remaining processes"
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
if pgrep -f snmpsim-command-responder &>/dev/null; then
|
||||||
|
pkill -f snmpsim-command-responder
|
||||||
|
ok "Killed remaining snmpsim processes"
|
||||||
|
else
|
||||||
|
skip "No snmpsim processes running"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if pgrep -f nflow-generator &>/dev/null; then
|
||||||
|
pkill -f nflow-generator
|
||||||
|
ok "Killed nflow-generator process"
|
||||||
|
else
|
||||||
|
skip "No nflow-generator process running"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
section "Step 3: Remove systemd unit files"
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
for f in "${SERVICE_FILES[@]}"; do
|
||||||
|
if [[ -f "$f" ]]; then
|
||||||
|
rm -f "$f"
|
||||||
|
ok "Removed: $f"
|
||||||
|
else
|
||||||
|
skip "Not found: $f"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
ok "systemd daemon reloaded"
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
section "Step 4: Remove install directory"
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
if [[ -d "$INSTALL_DIR" ]]; then
|
||||||
|
rm -rf "$INSTALL_DIR"
|
||||||
|
ok "Removed: $INSTALL_DIR"
|
||||||
|
else
|
||||||
|
skip "Not found: $INSTALL_DIR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
section "Step 5: Remove PID directory and cache"
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
if [[ -d "$PID_DIR" ]]; then
|
||||||
|
rm -rf "$PID_DIR"
|
||||||
|
ok "Removed: $PID_DIR"
|
||||||
|
else
|
||||||
|
skip "Not found: $PID_DIR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -d "$CACHE_DIR" ]]; then
|
||||||
|
rm -rf "$CACHE_DIR"
|
||||||
|
ok "Removed: $CACHE_DIR"
|
||||||
|
else
|
||||||
|
skip "Not found: $CACHE_DIR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
section "Step 6: snmpsim pip package"
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
if [[ $KEEP_PIP -eq 1 ]]; then
|
||||||
|
skip "Keeping snmpsim pip package (--keep-pip)"
|
||||||
|
else
|
||||||
|
if pip3 show snmpsim-lextudio &>/dev/null 2>&1; then
|
||||||
|
pip3 uninstall -y snmpsim-lextudio
|
||||||
|
ok "Uninstalled: snmpsim-lextudio"
|
||||||
|
elif pip3 show snmpsim &>/dev/null 2>&1; then
|
||||||
|
pip3 uninstall -y snmpsim
|
||||||
|
ok "Uninstalled: snmpsim"
|
||||||
|
else
|
||||||
|
skip "snmpsim pip package not found"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remove leftover snmpsim binaries
|
||||||
|
for bin in snmpsim-command-responder snmpsim-record-mibs; do
|
||||||
|
path=$(command -v "$bin" 2>/dev/null || true)
|
||||||
|
if [[ -n "$path" ]]; then
|
||||||
|
rm -f "$path"
|
||||||
|
ok "Removed binary: $path"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
section "Step 7: snmpsim system user"
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
if [[ $KEEP_USER -eq 1 ]]; then
|
||||||
|
skip "Keeping snmpsim user (--keep-user)"
|
||||||
|
else
|
||||||
|
if id "$SNMPSIM_USER" &>/dev/null; then
|
||||||
|
userdel "$SNMPSIM_USER"
|
||||||
|
ok "Removed user: $SNMPSIM_USER"
|
||||||
|
else
|
||||||
|
skip "User not found: $SNMPSIM_USER"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
section "Step 8: Remove cron entries (if any)"
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
if crontab -l 2>/dev/null | grep -q "trap-generator"; then
|
||||||
|
crontab -l 2>/dev/null | grep -v "trap-generator" | crontab -
|
||||||
|
ok "Removed trap-generator cron entry"
|
||||||
|
else
|
||||||
|
skip "No trap-generator cron entry found"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
# Done
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
echo ""
|
||||||
|
echo -e "${GREEN}╔══════════════════════════════════════════════════╗${NC}"
|
||||||
|
echo -e "${GREEN}║ Uninstall complete ║${NC}"
|
||||||
|
echo -e "${GREEN}╚══════════════════════════════════════════════════╝${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
KEPT=()
|
||||||
|
[[ $KEEP_PIP -eq 1 ]] && KEPT+=("snmpsim pip package")
|
||||||
|
[[ $KEEP_USER -eq 1 ]] && KEPT+=("snmpsim system user")
|
||||||
|
|
||||||
|
if [[ ${#KEPT[@]} -gt 0 ]]; then
|
||||||
|
echo -e " Kept (by request):"
|
||||||
|
for item in "${KEPT[@]}"; do
|
||||||
|
echo -e " ${YELLOW}${item}${NC}"
|
||||||
|
done
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e " Not removed (system packages):"
|
||||||
|
echo -e " Python 3, pip, Go, git, net-snmp-utils"
|
||||||
|
echo ""
|
||||||
|
echo -e " Ready for a fresh install:"
|
||||||
|
echo -e " ${CYAN}sudo ./install-snmpsim-lab.sh --vm-ip <IP> --trap-host <IP> --netflow-host <IP>${NC}"
|
||||||
|
echo ""
|
||||||
BIN
uninstall-snmpsim-lab.sh:Zone.Identifier
Normal file
BIN
uninstall-snmpsim-lab.sh:Zone.Identifier
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user