secubox-openwrt/secubox-tools/lxc/secubox-lxc

172 lines
4.6 KiB
Bash
Executable File

#!/bin/sh
# SecuBox LXC helper: create/start/stop LXC containers following SecuBox conventions
set -eu
CONFIG="/etc/config/lxcapps"
STORAGE_ROOT="/srv/lxc"
TEMPLATE_DIR="${SECUBOX_LXC_TEMPLATES:-/usr/share/secubox/lxc/templates}"
usage() {
cat <<'USAGE'
SecuBox LXC Manager
Usage: secubox-lxc <command> [options]
Commands:
list Show containers defined in /etc/config/lxcapps
show <name> Display config values for a container
create <name> [options] Create container (downloads template if needed)
start <name> Start container via lxc-start
stop <name> Stop container via lxc-stop
delete <name> Stop and remove container directory
status <name> Show runtime state
Options (create):
--template PATH Rootfs tarball or template script (default debian)
--bridge BRIDGE Bridge to attach (default br-lan)
--ip ADDRESS Static IP address (optional)
--gateway ADDRESS Gateway (optional)
--dns ADDRESS DNS server (optional)
--memory MB Memory limit (optional)
Examples:
secubox-lxc list
secubox-lxc create secubox-lyrion --bridge br-dmz --ip 192.168.50.10
secubox-lxc start secubox-lyrion
USAGE
}
require_tool() {
command -v "$1" >/dev/null 2>&1 || { echo "[ERROR] Missing dependency: $1" >&2; exit 1; }
}
ensure_storage() {
mkdir -p "$STORAGE_ROOT"
}
uci_get_container() {
local name="$1" option="$2"
uci -q get lxcapps."$name"."$2"
}
uci_set_container() {
local name="$1" option="$2" value="$3"
uci set lxcapps."$name"."$option"="$value"
}
list_containers() {
uci -q show lxcapps 2>/dev/null | grep '=container$' | cut -d. -f2 | cut -d= -f1
}
cmd_list() {
require_tool lxc-info
ensure_storage
printf '%-18s %-20s %-10s %-16s\n' "Name" "Bridge" "State" "RootFS"
printf '%-18s %-20s %-10s %-16s\n' "----" "------" "-----" "------"
for name in $(list_containers); do
local bridge rootfs state
bridge=$(uci_get_container "$name" bridge || printf 'br-lan')
rootfs="$STORAGE_ROOT/$name/rootfs"
if lxc-info -n "$name" >/dev/null 2>&1; then
state=$(lxc-info -n "$name" -s 2>/dev/null | awk '{print $2}')
else
state="N/A"
fi
printf '%-18s %-20s %-10s %-16s\n' "$name" "$bridge" "$state" "$rootfs"
done
}
cmd_show() {
local name="$1"
uci -q show lxcapps."$name"
}
cmd_create() {
require_tool lxc-create
local name="$1"; shift
local template="debian"
local bridge="br-lan"
local ip=""
local gateway=""
local dns=""
local memory=""
while [ $# -gt 0 ]; do
case "$1" in
--template) template="$2"; shift 2;;
--bridge) bridge="$2"; shift 2;;
--ip) ip="$2"; shift 2;;
--gateway) gateway="$2"; shift 2;;
--dns) dns="$2"; shift 2;;
--memory) memory="$2"; shift 2;;
*) echo "Unknown option: $1" >&2; exit 1;;
esac
done
[ -n "$name" ] || { echo "Container name required" >&2; exit 1; }
ensure_storage
local container_dir="$STORAGE_ROOT/$name"
if [ -d "$container_dir" ]; then
echo "[WARN] Container directory already exists, skipping rootfs creation."
else
mkdir -p "$container_dir"
local tmpl_path="$template"
if [ -f "$TEMPLATE_DIR/$template" ]; then
tmpl_path="$TEMPLATE_DIR/$template"
fi
lxc-create -n "$name" -P "$STORAGE_ROOT" -t "$tmpl_path"
fi
uci batch <<-EOF
set lxcapps.$name=container
set lxcapps.$name.bridge='$bridge'
EOF
[ -n "$ip" ] && uci_set_container "$name" ip "$ip"
[ -n "$gateway" ] && uci_set_container "$name" gateway "$gateway"
[ -n "$dns" ] && uci_set_container "$name" dns "$dns"
[ -n "$memory" ] && uci_set_container "$name" memory "$memory"
uci commit lxcapps
cat <<MSG
[INFO] Container $name created.
Rootfs: $container_dir
Bridge: $bridge
MSG
}
cmd_start() {
require_tool lxc-start
local name="$1"
lxc-start -n "$name" -d
}
cmd_stop() {
require_tool lxc-stop
local name="$1"
lxc-stop -n "$name"
}
cmd_delete() {
require_tool lxc-destroy
local name="$1"
lxc-stop -n "$name" >/dev/null 2>&1 || true
lxc-destroy -n "$name"
rm -rf "$STORAGE_ROOT/$name"
uci delete lxcapps."$name"
uci commit lxcapps
}
cmd_status() {
require_tool lxc-info
local name="$1"
lxc-info -n "$name"
}
case "${1:-}" in
list) shift; cmd_list "$@" ;;
show) shift; [ $# -ge 1 ] || { usage; exit 1; }; cmd_show "$1" ;;
create) shift; [ $# -ge 1 ] || { usage; exit 1; }; cmd_create "$@" ;;
start) shift; [ $# -ge 1 ] || { usage; exit 1; }; cmd_start "$1" ;;
stop) shift; [ $# -ge 1 ] || { usage; exit 1; }; cmd_stop "$1" ;;
delete) shift; [ $# -ge 1 ] || { usage; exit 1; }; cmd_delete "$1" ;;
status) shift; [ $# -ge 1 ] || { usage; exit 1; }; cmd_status "$1" ;;
help|--help|-h|'') usage ;;
*) usage; exit 1 ;;
esac