mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-07-28 03:01:54 +08:00
268 lines
7.1 KiB
Bash
Executable File
268 lines
7.1 KiB
Bash
Executable File
#!/bin/sh
|
|
# Author jjm2473@gmail.com
|
|
|
|
ACTION="${1}"
|
|
shift 1
|
|
|
|
do_install() {
|
|
local id="`uci get shadowrt.@instance[0].id 2>/dev/null`"
|
|
local data="`uci get shadowrt.@instance[0].data 2>/dev/null`"
|
|
local mnt="`uci get shadowrt.@instance[0].mnt 2>/dev/null`"
|
|
local proto=`uci get shadowrt.@instance[0].proto 2>/dev/null`
|
|
local address=`uci get shadowrt.@instance[0].address 2>/dev/null`
|
|
local gateway=`uci get shadowrt.@instance[0].gateway 2>/dev/null`
|
|
local dns="`uci get shadowrt.@instance[0].dns 2>/dev/null`"
|
|
local dhcp_server=`uci get shadowrt.@instance[0].dhcp_server 2>/dev/null`
|
|
local ports="`uci get shadowrt.@instance[0].ports 2>/dev/null`"
|
|
|
|
if [ -z "$data" ]; then
|
|
echo "data path is empty!" >&2
|
|
exit 1
|
|
fi
|
|
|
|
[ -s /rom/etc/openwrt_release ] || {
|
|
echo "/rom is not a openwrt rootfs!" >&2
|
|
exit 1
|
|
}
|
|
|
|
if [ "$proto" = "static" ]; then
|
|
if [ -z "$address" ]; then
|
|
echo "static ip requires address!" >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
/etc/init.d/docker-lan start || {
|
|
echo "create docker-lan bridge failed!" >&2
|
|
exit 1
|
|
}
|
|
|
|
local alpine_image="alpine:3.22.2"
|
|
if ! docker image inspect -f '{}' "$alpine_image" >/dev/null 2>&1; then
|
|
echo "pulling alpine image $alpine_image ..."
|
|
docker pull "$alpine_image" || exit 1
|
|
fi
|
|
|
|
if [ -d "$data/$id" ]; then
|
|
echo "WARNING: $data/$id already exists, may use old data." >&2
|
|
fi
|
|
|
|
local config="{\"id\":\"$id\",\"data\":\"$data\",\"mnt\":\"$mnt\",\"proto\":\"$proto\",\"address\":\"$address\",\"gateway\":\"$gateway\",\"dns\":\"$dns\",\"dhcp_server\":\"$dhcp_server\",\"ports\":\"$ports\"}"
|
|
|
|
local cmd="docker run --restart=unless-stopped -d \
|
|
--stop-signal SIGINT \
|
|
--stop-timeout 30 \
|
|
--security-opt seccomp=unconfined \
|
|
--security-opt apparmor=unconfined \
|
|
--cap-add=SYS_ADMIN \
|
|
--cap-add=SYS_CHROOT \
|
|
--cap-drop=MKNOD \
|
|
--cap-add=LEASE \
|
|
--cap-add=SETGID \
|
|
--cap-add=SETUID \
|
|
--cap-add=NET_ADMIN \
|
|
--cap-add=NET_RAW \
|
|
--cap-add=NET_BIND_SERVICE \
|
|
--network docker-lan \
|
|
-v /usr/share/shadowrt/container:/shadowrt:ro \
|
|
--entrypoint /shadowrt/entrypoint.sh \
|
|
-v /dev/net:/dev/net \
|
|
--device /dev/fuse:/dev/fuse \
|
|
-v /rom:/rom:ro \
|
|
--label creator=shadowrt \
|
|
--name '$id' \
|
|
--hostname '$id' \
|
|
--label 'com.shadowrt.config=$config' \
|
|
-v '$data/$id/overlay:/overlay:rw' "
|
|
|
|
[ -n "$proto" ] && cmd="$cmd -e IP_PROTO=$proto"
|
|
if [ "$proto" = "static" ]; then
|
|
[ -n "$address" ] && cmd="$cmd -e IP_ADDRESS=$address"
|
|
[ -n "$gateway" ] && cmd="$cmd -e IP_GATEWAY=$gateway"
|
|
[ -n "$dns" ] && cmd="$cmd -e 'IP_DNS=$dns'"
|
|
fi
|
|
[ "$dhcp_server" = "1" -o "$dhcp_server" = "on" ] && cmd="$cmd -e DHCP_SERVER=on"
|
|
if [ -n "$ports" ]; then
|
|
for p in $ports; do
|
|
cmd="$cmd -p $p:$p"
|
|
done
|
|
fi
|
|
if [ -n "$dns" ]; then
|
|
for d in $dns; do
|
|
cmd="$cmd --dns $d"
|
|
done
|
|
fi
|
|
|
|
local tz="`uci get system.@system[0].zonename | sed 's/ /_/g'`"
|
|
[ -z "$tz" ] || cmd="$cmd -e TZ=$tz"
|
|
|
|
if [ "$mnt" = "1" -o "$mnt" = "on" ]; then
|
|
cmd="$cmd -v /mnt:/mnt"
|
|
mountpoint -q /mnt && cmd="$cmd:rshared"
|
|
fi
|
|
cmd="$cmd $alpine_image"
|
|
|
|
echo "stopping existing container..."
|
|
docker stop "$id" >/dev/null 2>&1
|
|
docker rm -f "$id"
|
|
|
|
echo "starting shadowrt instance $id..."
|
|
echo "$cmd"
|
|
eval "$cmd"
|
|
|
|
}
|
|
|
|
do_ls() {
|
|
local name state ip
|
|
|
|
echo "["
|
|
docker ps -a -f 'label=creator=shadowrt' --format '{{.Names}} {{.State}}' | sort -n | while read name state; do
|
|
ip=
|
|
if [ "$state" = "running" ]; then
|
|
ip=`docker exec "$name" ip addr show dev br-lan | grep -m1 'inet ' | head -1 | sed -nE 's#.*inet ([0-9\.]*)/([0-9]*) .*#\1#p'`
|
|
if [ -z "$ip" ]; then
|
|
docker exec "$name" test -e /etc/openwrt_release -a ! -e /rom/note || state="starting"
|
|
fi
|
|
fi
|
|
echo '{"name":"'"$name"'","status":"'"$state"'","ip":"'"$ip"'"},'
|
|
#docker container inspect -f '{"name":"'"$name"'","status":"'"$state"'","config":{{index .Config.Labels "com.shadowrt.config"}},"ip":"'"$ip"'"},' "$name"
|
|
done | head -c -2
|
|
echo ""
|
|
echo "]"
|
|
}
|
|
|
|
do_clone() {
|
|
local config_json="`docker container inspect -f '{{index .Config.Labels "com.shadowrt.config"}}' "$1"`"
|
|
[ -z "$config_json" ] && {
|
|
echo "container $1 not found!" >&2
|
|
return 1
|
|
}
|
|
{
|
|
echo "delete shadowrt.@instance[0]"
|
|
echo "add shadowrt instance"
|
|
echo "$config_json" | jsonfilter -e 'id=$.id' \
|
|
-e 'data=$.data' \
|
|
-e 'mnt=$.mnt' \
|
|
-e 'proto=$.proto' \
|
|
-e 'address=$.address' \
|
|
-e 'gateway=$.gateway' \
|
|
-e 'dns=$.dns' \
|
|
-e 'dhcp_server=$.dhcp_server' \
|
|
-e 'ports=$.ports' | sed -e 's/; /\n/g' | sed -e 's/^export /set shadowrt.@instance[0]./g'
|
|
echo "commit shadowrt"
|
|
} | uci batch
|
|
|
|
return 0
|
|
}
|
|
|
|
do_reset_network() {
|
|
local name="$1"
|
|
local running=false
|
|
local shell
|
|
|
|
docker exec "$name" test -e /etc/openwrt_release -a ! -e /rom/note >/dev/null 2>&1 && running=true
|
|
if $running; then
|
|
shell="exec docker exec -i -w / '$name' /bin/sh"
|
|
else
|
|
docker stop "$name" >/dev/null 2>&1
|
|
local data="`docker container inspect -f '{{index .Config.Labels "com.shadowrt.config"}}' "$name" | jsonfilter -e '$.data'`"
|
|
local dir="$data/$name/overlay/upper"
|
|
[ -d "$dir" ] || return 0
|
|
shell="cd '$dir' && exec /bin/sh"
|
|
fi
|
|
{
|
|
cat <<-EOF
|
|
for f in etc/config/network etc/board.json; do
|
|
rm -f "\$f"
|
|
done
|
|
EOF
|
|
if $running; then
|
|
cat <<-EOF
|
|
/bin/board_detect
|
|
/bin/config_generate
|
|
/bin/sh -c ". /rom/etc/uci-defaults/zzz-dockerenv"
|
|
/bin/sh -c '. /rom/etc/uci-defaults/12_network-generate-ula'
|
|
/etc/init.d/network restart
|
|
sleep 2
|
|
EOF
|
|
else
|
|
echo 'rm -f etc/uci-defaults/zzz-dockerenv etc/uci-defaults/12_network-generate-ula'
|
|
fi
|
|
} | sh -c "$shell"
|
|
}
|
|
|
|
check_all_ready() {
|
|
local names="$1"
|
|
local name
|
|
local ret=0
|
|
for name in $names; do
|
|
if ! docker exec "$name" test -e /etc/openwrt_release -a ! -e /rom/note; then
|
|
ret=1
|
|
break
|
|
fi
|
|
done
|
|
return $ret
|
|
}
|
|
|
|
usage() {
|
|
echo "usage: $0 sub-command"
|
|
echo "where sub-command is one of:"
|
|
echo " install Install/Replace a instance"
|
|
echo " ls List all instances"
|
|
echo " rm/start/stop/restart {ID} Remove/Start/Stop/Restart the instance"
|
|
echo " clone {ID} Clone an existing instance to uci"
|
|
echo " rmd {ID} Remove an existing instance and its data"
|
|
echo " reset_network {ID} Reset network configuration inside the instance"
|
|
echo " status Dummy status for taskd"
|
|
|
|
}
|
|
|
|
case "${ACTION}" in
|
|
"install")
|
|
do_install
|
|
;;
|
|
"rm" | "rmd")
|
|
if [ -n "$1" ]; then
|
|
docker stop "$1" >/dev/null 2>&1
|
|
if [ "$ACTION" = "rmd" ]; then
|
|
data="`docker container inspect -f '{{index .Config.Labels "com.shadowrt.config"}}' "$1" | jsonfilter -e '$.data'`"
|
|
[ -n "$data" ] && rm -rf "$data/$1"
|
|
fi
|
|
docker rm -f "$1"
|
|
fi
|
|
;;
|
|
"reset_network")
|
|
if [ -n "$1" ]; then
|
|
do_reset_network "$1"
|
|
fi
|
|
;;
|
|
"start" | "stop" | "restart")
|
|
if [ -n "$1" ]; then
|
|
docker "${ACTION}" $1
|
|
if [ "$ACTION" = "start" -o "$ACTION" = "restart" ]; then
|
|
sleep 2
|
|
for i in $(seq 1 5); do
|
|
check_all_ready "$1" && break
|
|
sleep 1
|
|
done
|
|
fi
|
|
fi
|
|
;;
|
|
"clone")
|
|
if [ -n "$1" ]; then
|
|
do_clone "$1" || exit 1
|
|
fi
|
|
;;
|
|
"status")
|
|
# hack, return empty string, so lib-taskd thinks container is not installed
|
|
exit 0
|
|
;;
|
|
"ls")
|
|
do_ls
|
|
;;
|
|
*)
|
|
usage
|
|
exit 1
|
|
;;
|
|
esac
|