mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-10-28 00:32:51 +08:00
339 lines
9.6 KiB
Bash
Executable File
339 lines
9.6 KiB
Bash
Executable File
#!/bin/sh
|
|
# ubus RPC module for Quick Actions Scripts
|
|
. /usr/share/libubox/jshn.sh
|
|
|
|
SCRIPTS_DIR=/etc/quickactions/scripts
|
|
mkdir -p "$SCRIPTS_DIR"
|
|
|
|
list_methods() {
|
|
cat <<'EOF'
|
|
{
|
|
"list": {},
|
|
"read": { "sid": "string" },
|
|
"write": { "sid": "string", "name": "string", "category": "string", "content": "string", "args": "string", "timeout": "string", "enabled": "string" },
|
|
"delete": { "sid": "string" },
|
|
"run": { "sid": "string" },
|
|
"chmod": { "sid": "string", "mode": "string" },
|
|
"install_preset": { "preset": "string" },
|
|
"detail": { "sid": "string" }
|
|
}
|
|
EOF
|
|
}
|
|
|
|
method_list() {
|
|
cat >/dev/null
|
|
json_init
|
|
json_add_array "scripts"
|
|
# No pipe into while → no subshell → json_add works
|
|
for sid in $(uci show quickactions 2>/dev/null | grep '=script$' | cut -d. -f2 | cut -d= -f1); do
|
|
name=$(uci -q get "quickactions.$sid.name")
|
|
category=$(uci -q get "quickactions.$sid.category")
|
|
path=$(uci -q get "quickactions.$sid.path")
|
|
[ -z "$path" ] && path="$SCRIPTS_DIR/$sid.sh"
|
|
enabled=$(uci -q get "quickactions.$sid.enabled")
|
|
[ -z "$enabled" ] && enabled="1"
|
|
sz=0
|
|
[ -f "$path" ] && sz=$(wc -c < "$path" 2>/dev/null)
|
|
[ -z "$sz" ] && sz=0
|
|
json_add_object
|
|
json_add_string "sid" "$sid"
|
|
json_add_string "name" "$name"
|
|
json_add_string "category" "$category"
|
|
json_add_string "path" "$path"
|
|
json_add_string "enabled" "$enabled"
|
|
json_add_int "size" "$sz"
|
|
json_close_object
|
|
done
|
|
json_close_array
|
|
json_dump
|
|
}
|
|
|
|
method_read() {
|
|
local sid=""
|
|
json_load "$(cat)"
|
|
json_get_var sid "sid"
|
|
[ -z "$sid" ] && { json_init; json_add_string "error" "no sid"; json_dump; return; }
|
|
|
|
local path
|
|
path=$(uci -q get "quickactions.$sid.path")
|
|
[ -z "$path" ] && path="$SCRIPTS_DIR/$sid.sh"
|
|
|
|
json_init
|
|
if [ -f "$path" ]; then
|
|
json_add_string "content" "$(cat "$path")"
|
|
else
|
|
json_add_string "content" ""
|
|
fi
|
|
json_dump
|
|
}
|
|
|
|
method_write() {
|
|
local payload sid name category content args timeout enabled path
|
|
payload=$(cat)
|
|
json_load "$payload"
|
|
json_get_var sid "sid"
|
|
json_get_var name "name"
|
|
json_get_var category "category"
|
|
json_get_var content "content"
|
|
json_get_var args "args"
|
|
json_get_var timeout "timeout"
|
|
json_get_var enabled "enabled"
|
|
|
|
[ -z "$sid" ] && sid="script_$(date +%s)"
|
|
[ -z "$name" ] && name="$sid"
|
|
[ -z "$category" ] && category="custom"
|
|
[ -z "$timeout" ] && timeout="60"
|
|
[ -z "$enabled" ] && enabled="1"
|
|
|
|
path=$(uci -q get "quickactions.$sid.path")
|
|
[ -z "$path" ] && path="$SCRIPTS_DIR/$sid.sh"
|
|
|
|
mkdir -p "$(dirname "$path")"
|
|
printf '%s' "$content" > "$path"
|
|
chmod 755 "$path" 2>/dev/null
|
|
|
|
uci -q set "quickactions.$sid=script"
|
|
uci -q set "quickactions.$sid.name=$name"
|
|
uci -q set "quickactions.$sid.category=$category"
|
|
uci -q set "quickactions.$sid.path=$path"
|
|
uci -q set "quickactions.$sid.enabled=$enabled"
|
|
uci -q set "quickactions.$sid.timeout=$timeout"
|
|
[ -n "$args" ] && uci -q set "quickactions.$sid.args=$args"
|
|
uci -q commit quickactions
|
|
|
|
json_init
|
|
json_add_string "sid" "$sid"
|
|
json_add_boolean "ok" 1
|
|
json_dump
|
|
}
|
|
|
|
method_delete() {
|
|
local sid=""
|
|
json_load "$(cat)"
|
|
json_get_var sid "sid"
|
|
[ -z "$sid" ] && { json_init; json_add_boolean "ok" 0; json_dump; return; }
|
|
|
|
local path
|
|
path=$(uci -q get "quickactions.$sid.path")
|
|
[ -z "$path" ] && path="$SCRIPTS_DIR/$sid.sh"
|
|
[ -f "$path" ] && rm -f "$path"
|
|
|
|
uci -q delete "quickactions.$sid"
|
|
uci -q commit quickactions
|
|
|
|
json_init
|
|
json_add_boolean "ok" 1
|
|
json_dump
|
|
}
|
|
|
|
method_run() {
|
|
local sid=""
|
|
json_load "$(cat)"
|
|
json_get_var sid "sid"
|
|
[ -z "$sid" ] && { json_init; json_add_string "error" "no sid"; json_dump; return; }
|
|
|
|
local path timeout args
|
|
path=$(uci -q get "quickactions.$sid.path")
|
|
[ -z "$path" ] && path="$SCRIPTS_DIR/$sid.sh"
|
|
timeout=$(uci -q get "quickactions.$sid.timeout")
|
|
[ -z "$timeout" ] && timeout=60
|
|
args=$(uci -q get "quickactions.$sid.args")
|
|
|
|
if [ ! -f "$path" ]; then
|
|
json_init
|
|
json_add_string "output" "Script not found: $path"
|
|
json_add_int "exit_code" 127
|
|
json_dump
|
|
return
|
|
fi
|
|
[ -x "$path" ] || chmod 755 "$path" 2>/dev/null
|
|
|
|
local start_sec end_sec out rc
|
|
start_sec=$(date +%s 2>/dev/null)
|
|
out=$(cd / && timeout "$timeout" "$path" $args 2>&1)
|
|
rc=$?
|
|
end_sec=$(date +%s 2>/dev/null)
|
|
|
|
json_init
|
|
json_add_string "output" "$out"
|
|
json_add_int "exit_code" "$rc"
|
|
json_add_int "duration" "$((end_sec - start_sec))"
|
|
json_dump
|
|
}
|
|
|
|
method_chmod() {
|
|
local payload sid mode
|
|
payload=$(cat)
|
|
json_load "$payload"
|
|
json_get_var sid "sid"
|
|
json_get_var mode "mode"
|
|
[ -z "$mode" ] && mode="755"
|
|
|
|
local path
|
|
path=$(uci -q get "quickactions.$sid.path")
|
|
[ -z "$path" ] && path="$SCRIPTS_DIR/$sid.sh"
|
|
|
|
[ -f "$path" ] && chmod "$mode" "$path" 2>/dev/null
|
|
|
|
json_init
|
|
json_add_boolean "ok" 1
|
|
json_dump
|
|
}
|
|
|
|
method_detail() {
|
|
local sid=""
|
|
json_load "$(cat)"
|
|
json_get_var sid "sid"
|
|
[ -z "$sid" ] && { json_init; json_add_string "error" "no sid"; json_dump; return; }
|
|
|
|
local path
|
|
path=$(uci -q get "quickactions.$sid.path")
|
|
[ -z "$path" ] && path="$SCRIPTS_DIR/$sid.sh"
|
|
|
|
json_init
|
|
json_add_string "sid" "$sid"
|
|
json_add_string "name" "$(uci -q get quickactions.$sid.name)"
|
|
json_add_string "category" "$(uci -q get quickactions.$sid.category)"
|
|
json_add_string "path" "$path"
|
|
json_add_string "enabled" "$(uci -q get quickactions.$sid.enabled)"
|
|
json_add_string "timeout" "$(uci -q get quickactions.$sid.timeout)"
|
|
json_add_string "args" "$(uci -q get quickactions.$sid.args)"
|
|
json_add_string "description" "$(uci -q get quickactions.$sid.description)"
|
|
if [ -f "$path" ]; then
|
|
json_add_string "content" "$(cat "$path")"
|
|
json_add_int "size" "$(wc -c < "$path")"
|
|
json_add_string "permissions" "$(ls -l "$path" | awk '{print $1}')"
|
|
else
|
|
json_add_string "content" ""
|
|
json_add_int "size" 0
|
|
json_add_string "permissions" ""
|
|
fi
|
|
json_dump
|
|
}
|
|
|
|
method_install_preset() {
|
|
local preset=""
|
|
json_load "$(cat)"
|
|
json_get_var preset "preset"
|
|
|
|
local sid="failover-lite"
|
|
local path="$SCRIPTS_DIR/$sid.sh"
|
|
mkdir -p "$SCRIPTS_DIR"
|
|
|
|
if [ "$preset" = "failover" ] || [ -z "$preset" ]; then
|
|
cat > "$path" << 'FO_EOF'
|
|
#!/bin/sh
|
|
# Failover-lite — MWAN3 substitute for low-RAM routers.
|
|
. /lib/functions.sh
|
|
config_load quickactions
|
|
cfg() { config_get v failover "$1" "$2"; echo "$v"; }
|
|
|
|
ENABLED=$(cfg enabled 1); [ "$ENABLED" = "0" ] && exit 0
|
|
PRIMARY=$(cfg primary ""); [ -z "$PRIMARY" ] && exit 0
|
|
CHECK_IPS=$(cfg check_ips "1.1.1.1 8.8.8.8")
|
|
PING_TIMEOUT=$(cfg ping_timeout 5)
|
|
FAIL_AT=$(cfg fail_threshold 2)
|
|
REC_AT=$(cfg recover_threshold 1)
|
|
|
|
LOCK=/tmp/qa-failover-preset.lock
|
|
FAIL_FILE=/tmp/qa-failover-preset.fails
|
|
OK_FILE=/tmp/qa-failover-preset.oks
|
|
|
|
phys_iface() {
|
|
local log="$1" dev
|
|
[ -e "/sys/class/net/pppoe-$log" ] && { echo "pppoe-$log"; return; }
|
|
case "$log" in *pppoe*) [ -e "/sys/class/net/$log" ] && { echo "$log"; return; } ;; esac
|
|
dev=$(uci -q get network.$log.device)
|
|
[ -n "$dev" ] && [ -e "/sys/class/net/$dev" ] && { echo "$dev"; return; }
|
|
echo "$log"
|
|
}
|
|
ping_ok() {
|
|
local iface="$1" ip
|
|
for ip in $CHECK_IPS; do
|
|
ping -I "$iface" -c 1 -W "$PING_TIMEOUT" "$ip" >/dev/null 2>&1 && return 0
|
|
done
|
|
return 1
|
|
}
|
|
flush_ct() {
|
|
[ -e /proc/net/nf_conntrack ] && echo f > /proc/net/nf_conntrack
|
|
[ -e /proc/net/ip_conntrack ] && echo f > /proc/net/ip_conntrack
|
|
return 0
|
|
}
|
|
|
|
DEV=$(phys_iface "$PRIMARY")
|
|
|
|
if [ -f "$LOCK" ]; then
|
|
OK_N=0; [ -f "$OK_FILE" ] && OK_N=$(cat "$OK_FILE")
|
|
if ping_ok "$DEV"; then
|
|
OK_N=$((OK_N + 1))
|
|
if [ "$OK_N" -ge "$REC_AT" ]; then
|
|
rm -f "$LOCK" "$FAIL_FILE" "$OK_FILE"
|
|
flush_ct
|
|
logger -t qa-failover-preset "PRIMARY $PRIMARY recovered"
|
|
else
|
|
echo "$OK_N" > "$OK_FILE"
|
|
fi
|
|
else
|
|
echo 0 > "$OK_FILE"
|
|
fi
|
|
exit 0
|
|
fi
|
|
|
|
if ping_ok "$DEV"; then
|
|
rm -f "$FAIL_FILE"
|
|
exit 0
|
|
fi
|
|
|
|
FAIL_N=0; [ -f "$FAIL_FILE" ] && FAIL_N=$(cat "$FAIL_FILE")
|
|
FAIL_N=$((FAIL_N + 1))
|
|
echo "$FAIL_N" > "$FAIL_FILE"
|
|
|
|
if [ "$FAIL_N" -ge "$FAIL_AT" ]; then
|
|
touch "$LOCK"; rm -f "$FAIL_FILE"; flush_ct
|
|
logger -t qa-failover-preset "PRIMARY $PRIMARY DOWN after $FAIL_AT failures"
|
|
fi
|
|
exit 0
|
|
FO_EOF
|
|
fi
|
|
|
|
chmod 755 "$path"
|
|
uci -q set "quickactions.$sid=script"
|
|
uci -q set "quickactions.$sid.name=Failover-lite"
|
|
uci -q set "quickactions.$sid.category=failover"
|
|
uci -q set "quickactions.$sid.path=$path"
|
|
uci -q set "quickactions.$sid.enabled=0"
|
|
uci -q set "quickactions.$sid.timeout=30"
|
|
uci -q set "quickactions.$sid.description=MWAN3 substitute: ping test + conntrack flush"
|
|
uci -q commit quickactions
|
|
|
|
json_init
|
|
json_add_string "sid" "$sid"
|
|
json_add_string "path" "$path"
|
|
json_add_boolean "ok" 1
|
|
json_dump
|
|
}
|
|
|
|
call_method() {
|
|
local method="$1"
|
|
case "$method" in
|
|
list) method_list ;;
|
|
read) method_read ;;
|
|
write) method_write ;;
|
|
delete) method_delete ;;
|
|
run) method_run ;;
|
|
chmod) method_chmod ;;
|
|
detail) method_detail ;;
|
|
install_preset) method_install_preset ;;
|
|
*) cat >/dev/null
|
|
json_init
|
|
json_add_string "error" "unknown_method"
|
|
json_dump ;;
|
|
esac
|
|
}
|
|
|
|
case "$1" in
|
|
list) list_methods ;;
|
|
call) call_method "$2" ;;
|
|
*) echo '{"error":"usage"}' ;;
|
|
esac
|