This commit is contained in:
siriling 2025-01-20 22:42:26 +08:00
parent afca024a11
commit 316e110a81
157 changed files with 2975 additions and 253 deletions

View File

@ -1,18 +1,17 @@
From 72f06f906ad22be173a25c3f50b61f9b1a33a16c Mon Sep 17 00:00:00 2001
From 55db7a1f7f650f965e783301387246f9f62fa1ec Mon Sep 17 00:00:00 2001
From: Liangbin Lian <jjm2473@gmail.com>
Date: Fri, 11 Mar 2022 19:16:05 +0800
Subject: [PATCH] i18n compatible with old luci sources
Date: Wed, 11 Dec 2024 11:20:45 +0800
Subject: [PATCH] luci.mk: postinst compat openwrt 23
Signed-off-by: Liangbin Lian <jjm2473@gmail.com>
---
luci.mk | 2 ++
1 file changed, 2 insertions(+)
luci.mk | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/luci.mk b/luci.mk
index b331ebe1c5e..7e9a823b8bd 100644
index aca52e08cd..b28284c892 100644
--- a/luci.mk
+++ b/luci.mk
@@ -50,6 +50,8 @@ LUCI_LANG.uk=Українська (Ukrainian)
@@ -53,6 +53,8 @@ LUCI_LANG.uk=Українська (Ukrainian)
LUCI_LANG.vi=Tiếng Việt (Vietnamese)
LUCI_LANG.zh_Hans=简体中文 (Chinese Simplified)
LUCI_LANG.zh_Hant=繁體中文 (Chinese Traditional)
@ -21,3 +20,26 @@ index b331ebe1c5e..7e9a823b8bd 100644
# Submenu titles
LUCI_MENU.col=1. Collections
@@ -211,8 +213,8 @@ endef
ifndef Package/$(PKG_NAME)/postinst
define Package/$(PKG_NAME)/postinst
[ -n "$${IPKG_INSTROOT}" ] || {$(foreach script,$(LUCI_DEFAULTS),
- (. /etc/uci-defaults/$(script)) && rm -f /etc/uci-defaults/$(script))
- rm -f /tmp/luci-indexcache
+ [ -f /etc/uci-defaults/$(script) ] && (. /etc/uci-defaults/$(script)) && rm -f /etc/uci-defaults/$(script))
+ rm -f /tmp/luci-indexcache /tmp/luci-indexcache.*
rm -rf /tmp/luci-modulecache/
killall -HUP rpcd 2>/dev/null
exit 0
@@ -325,7 +327,7 @@ define LuciTranslation
define Package/luci-i18n-$(LUCI_BASENAME)-$(1)/postinst
[ -n "$$$${IPKG_INSTROOT}" ] || {
- (. /etc/uci-defaults/luci-i18n-$(LUCI_BASENAME)-$(1)) && rm -f /etc/uci-defaults/luci-i18n-$(LUCI_BASENAME)-$(1)
+ [ -f /etc/uci-defaults/luci-i18n-$(LUCI_BASENAME)-$(1) ] && (. /etc/uci-defaults/luci-i18n-$(LUCI_BASENAME)-$(1)) && rm -f /etc/uci-defaults/luci-i18n-$(LUCI_BASENAME)-$(1)
exit 0
}
endef
--
2.46.0

View File

@ -64,11 +64,13 @@ jobs:
DEBIAN_FRONTEND: noninteractive
run: |
sudo swapoff -a || true
sudo rm -rf /swapfile /etc/apt/sources.list.d/* /usr/share/dotnet /usr/local/lib/android /opt/ghc
sudo rm -rf /swapfile /usr/share/dotnet /usr/local/lib/android /opt/ghc
sudo find /etc/apt/sources.list.d ! -name 'ubuntu.sources' -type f -exec rm -f {} +
sudo -E apt-get -qq update
sudo -E apt-get -qq install build-essential asciidoc binutils bzip2 gawk gettext git libncurses5-dev libz-dev patch unzip zlib1g-dev libc6-dev-i386 subversion flex uglifyjs gcc-multilib g++-multilib p7zip p7zip-full msmtp libssl-dev texinfo libglib2.0-dev xmlto qemu-utils upx libelf-dev autoconf automake libtool autopoint device-tree-compiler antlr3 gperf rsync
sudo -E apt-get -qq autoremove --purge
sudo -E apt-get -qq clean
sudo ln -s /usr/bin/python3 /usr/bin/python3.10 || true
sudo timedatectl set-timezone "$TZ"
# curl -fsSL https://raw.githubusercontent.com/P3TERX/dotfiles/master/.bashrc >> ~/.bashrc

View File

@ -1,7 +1,7 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.0.4-20230408
PKG_VERSION:=1.0.5-20241208
PKG_RELEASE:=
PKG_MAINTAINER:=jjm2473 <jjm2473@gmail.com>

View File

@ -111,14 +111,15 @@ EOF
[[ "`uci -q get network.lan.proto`" = "static" ]] && {
local lan_ip="`uci -q get network.lan.ipaddr`"
if [[ -n "$lan_ip" ]]; then
if echo "$lan_ip" | grep -Fq '/'; then
for bip in $lan_ip; do
eval "$(ipcalc.sh ${bip/\// } )";black_ip="$black_ip $IP/$PREFIX"
done
else
local netmask="`uci -q get network.lan.netmask`"
eval "$(ipcalc.sh "$lan_ip" "$netmask" )";black_ip="$black_ip $IP/$PREFIX"
fi
local netmask="`uci -q get network.lan.netmask`"
[[ -n "$netmask" ]] || netmask=255.255.255.255
for bip in $lan_ip; do
if [[ "$bip" = "*/*" ]]; then
eval "$(ipcalc.sh $bip )";black_ip="$black_ip $IP/$PREFIX"
else
eval "$(ipcalc.sh $bip $netmask )";black_ip="$black_ip $IP/$PREFIX"
fi
done
fi
}
@ -133,32 +134,31 @@ EOF
local vif
for vif in lan wan; do
config_get ipaddr $vif ipaddr
[[ -z "$ipaddr" ]] || {
for vip in $ipaddr; do
ok=1
eval "$(ipcalc.sh ${vip/\// } )";vip="$IP";vip_p="$PREFIX"
[[ "$vip_p" = 32 ]] && {
[[ -n "$ipaddr" ]] || continue
for vip in $ipaddr; do
ok=1
[[ "$vip" = "*/*" ]] || vip="$vip/24"
eval "$(ipcalc.sh $vip )";vip="$IP";vip_p="$PREFIX"
[[ "$vip_p" = 32 ]] && {
logger -t 'ap_modem' -p DEBUG "vap_$vif skip $vip/$vip_p"
break
}
for bip in $black_ip; do
eval "$(ipcalc.sh "$bip" )";bip="$IP";
[[ "$PREFIX" -le "$vip_p" ]] || PREFIX=$vip_p
eval "$(ipcalc.sh "$vip/$PREFIX" )";vnet="$NETWORK";
eval "$(ipcalc.sh "$bip/$PREFIX" )";bnet="$NETWORK";
if [[ "$vnet" = "$bnet" ]]; then
logger -t 'ap_modem' -p DEBUG "vap_$vif skip $vip/$vip_p"
ok=0
break
}
[[ "$vip_p" = 0 ]] && vip_p=24
for bip in $black_ip; do
eval "$(ipcalc.sh "$bip" )";bip="$IP";
[[ "$PREFIX" -le "$vip_p" ]] || PREFIX=$vip_p
eval "$(ipcalc.sh "$vip" "$PREFIX" )";vnet="$NETWORK";
eval "$(ipcalc.sh "$bip" "$PREFIX" )";bnet="$NETWORK";
if [[ "$vnet" = "$bnet" ]]; then
logger -t 'ap_modem' -p DEBUG "vap_$vif skip $vip/$vip_p"
ok=0
break
fi
done
[[ "$ok" = 1 ]] && {
uci add_list "network.vap_$vif.ipaddr=$vip/$vip_p"
black_ip="$black_ip $vip/$vip_p"
}
fi
done
}
[[ "$ok" = 1 ]] && {
uci add_list "network.vap_$vif.ipaddr=$vip/$vip_p"
black_ip="$black_ip $vip/$vip_p"
}
done
done
uci commit network

View File

@ -0,0 +1,19 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=0.0.2-1
PKG_RELEASE:=
LUCI_TITLE:=LuCI support for arcadia
LUCI_PKGARCH:=all
LUCI_DEPENDS:=+lsblk +docker +luci-lib-taskd
define Package/luci-app-arcadia/conffiles
/etc/config/arcadia
endef
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature

View File

@ -0,0 +1,7 @@
module("luci.controller.arcadia", package.seeall)
function index()
entry({"admin", "services", "arcadia"}, alias("admin", "services", "arcadia", "config"), _("Arcadia"), 30).dependent = true
entry({"admin", "services", "arcadia", "config"}, cbi("arcadia"))
end

View File

@ -0,0 +1,55 @@
local util = require "luci.util"
local jsonc = require "luci.jsonc"
local arcadia = {}
arcadia.blocks = function()
local f = io.popen("lsblk -s -f -b -o NAME,FSSIZE,MOUNTPOINT --json", "r")
local vals = {}
if f then
local ret = f:read("*all")
f:close()
local obj = jsonc.parse(ret)
for _, val in pairs(obj["blockdevices"]) do
local fsize = val["fssize"]
if fsize ~= nil and string.len(fsize) > 10 and val["mountpoint"] then
-- fsize > 1G
vals[#vals+1] = val["mountpoint"]
end
end
end
return vals
end
arcadia.home = function()
local uci = require "luci.model.uci".cursor()
local home_dirs = {}
home_dirs["main_dir"] = uci:get_first("quickstart", "main", "main_dir", "/root")
home_dirs["Configs"] = uci:get_first("quickstart", "main", "conf_dir", home_dirs["main_dir"].."/Configs")
home_dirs["Public"] = uci:get_first("quickstart", "main", "pub_dir", home_dirs["main_dir"].."/Public")
home_dirs["Downloads"] = uci:get_first("quickstart", "main", "dl_dir", home_dirs["Public"].."/Downloads")
home_dirs["Caches"] = uci:get_first("quickstart", "main", "tmp_dir", home_dirs["main_dir"].."/Caches")
return home_dirs
end
arcadia.find_paths = function(blocks, home_dirs, path_name)
local default_path = ''
local configs = {}
default_path = home_dirs[path_name] .. "/Arcadia"
if #blocks == 0 then
table.insert(configs, default_path)
else
for _, val in pairs(blocks) do
table.insert(configs, val .. "/" .. path_name .. "/Arcadia")
end
local without_conf_dir = "/root/" .. path_name .. "/Arcadia"
if default_path == without_conf_dir then
default_path = configs[1]
end
end
return configs, default_path
end
return arcadia

View File

@ -0,0 +1,55 @@
--[[
LuCI - Lua Configuration Interface
]]--
local taskd = require "luci.model.tasks"
local arcadia_model = require "luci.model.arcadia"
local m, s, o
m = taskd.docker_map("arcadia", "arcadia", "/usr/libexec/istorec/arcadia.sh",
translate("Arcadia"),
translate("Arcadia one-stop code operation and maintenance platform.")
.. translate("Official website:") .. ' <a href=\"https://arcadia.cool\" target=\"_blank\">https://arcadia.cool</a>'
.. "<dl><dt>" .. translate("Arcadia is mainly aimed at scripting language programming and is suitable for development and operation environments of small and medium-sized teams and individuals.") .. "</dt>"
.. "<dt>" .. translate("In addition to code maintenance, Arcadia is also a powerful scheduled task maintenance platform with a comprehensive file system and underlying CLI command design.") .. "</dt>"
.. "<dt>" .. translate("The initial username and password are 'useradmin' and 'passwd' respectively.") .. "</dt>"
.. "</dl>")
s = m:section(SimpleSection, translate("Service Status"), translate("Arcadia status:"))
s:append(Template("arcadia/status"))
s = m:section(TypedSection, "arcadia", translate("Setup"),
translate("The initial installation of Arcadia requires at least 2GB of space, please make sure that the Docker data directory has enough space. It is recommended to migrate Docker to a hard drive before installing Arcadia.")
.. "<br>" .. translate("The following parameters will only take effect during installation or upgrade:"))
s.addremove=false
s.anonymous=true
o = s:option(Value, "image", translate("Image"))
o.datatype = "string"
o:value("", translate("Default"))
o:value("supermanito/arcadia:beta", "supermanito/arcadia:beta")
o:value("registry.cn-hangzhou.aliyuncs.com/supermanito/arcadia:beta", "registry.cn-hangzhou.aliyuncs.com/supermanito/arcadia:beta")
o = s:option(Flag, "hostnet", translate("Host network"), translate("Arcadia running in host network, port is always 5678 if enabled"))
o.default = 0
o.rmempty = false
o = s:option(Value, "port", translate("Port").."<b>*</b>")
o.default = "5678"
o.datatype = "port"
o:depends("hostnet", 0)
local blocks = arcadia_model.blocks()
local home = arcadia_model.home()
o = s:option(Value, "config_path", translate("Config path").."<b>*</b>")
o.rmempty = false
o.datatype = "string"
local paths, default_path = arcadia_model.find_paths(blocks, home, "Configs")
for _, val in pairs(paths) do
o:value(val, val)
end
o.default = default_path
return m

View File

@ -0,0 +1,31 @@
<%
local util = require "luci.util"
local container_status = util.trim(util.exec("/usr/libexec/istorec/arcadia.sh status"))
local container_install = (string.len(container_status) > 0)
local container_running = container_status == "running"
-%>
<div class="cbi-value">
<label class="cbi-value-title"><%:Status%></label>
<div class="cbi-value-field">
<% if container_running then %>
<button class="cbi-button cbi-button-success" disabled="true"><%:Arcadia is running%></button>
<% else %>
<button class="cbi-button cbi-button-negative" disabled="true"><%:Arcadia is not running%></button>
<% end %>
</div>
</div>
<%
if container_running then
local port=util.trim(util.exec("/usr/libexec/istorec/arcadia.sh port"))
if port == "" then
port="5678"
end
-%>
<div class="cbi-value cbi-value-last">
<label class="cbi-value-title">&nbsp;</label>
<div class="cbi-value-field">
<input type="button" class="btn cbi-button cbi-button-apply" name="start" value="<%:Open Arcadia%>" onclick="window.open('http://'+location.hostname+':<%=port%>/', '_blank')">
</div>
</div>
<% end %>

View File

@ -0,0 +1,62 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8"
msgid "Official website:"
msgstr "官方网站:"
msgid "Arcadia one-stop code operation and maintenance platform."
msgstr "Arcadia 一站式代码运维平台。"
msgid "Arcadia is mainly aimed at scripting language programming and is suitable for development and operation environments of small and medium-sized teams and individuals."
msgstr "Arcadia 主要面向于脚本语言编程,适用于中小型团队与个人的开发与运维环境。"
msgid "In addition to code maintenance, Arcadia is also a powerful scheduled task maintenance platform with a comprehensive file system and underlying CLI command design."
msgstr "除了代码运维外 Arcadia 还是一个强大的定时任务运维平台并且有着完善的文件系统和底层CLI命令设计。"
msgid "The initial username and password are 'useradmin' and 'passwd' respectively."
msgstr "初始的用户名和密码分别是'useradmin'和'passwd'。"
msgid "Image"
msgstr "镜像"
msgid "Default"
msgstr "默认"
msgid "Config path"
msgstr "配置文件路径"
msgid "Port"
msgstr "端口"
msgid "Host network"
msgstr "宿主网络"
msgid "Arcadia running in host network, port is always 5678 if enabled"
msgstr "在宿主网络运行 Arcadia如果启用则端口固定为5678"
msgid "Service Status"
msgstr "服务状态"
msgid "Arcadia status:"
msgstr "Arcadia 的状态信息如下:"
msgid "Setup"
msgstr "安装配置"
msgid "The initial installation of Arcadia requires at least 2GB of space, please make sure that the Docker data directory has enough space. It is recommended to migrate Docker to a hard drive before installing Arcadia."
msgstr "初次安装 Arcadia 至少需要2GB空间请确保 Docker 数据目录有足够空间。建议安装 Arcadia 前将 Docker 迁移到硬盘上。"
msgid "The following parameters will only take effect during installation or upgrade:"
msgstr "以下参数只在安装或者升级时才会生效:"
msgid "Status"
msgstr "状态"
msgid "Arcadia is running"
msgstr "Arcadia 运行中"
msgid "Arcadia is not running"
msgstr "Arcadia 未运行"
msgid "Open Arcadia"
msgstr "打开 Arcadia"

View File

@ -0,0 +1,5 @@
config arcadia
option 'hostnet' '0'
option 'port' '5678'
# option 'image' 'default'
# option 'config_path' ''

View File

@ -0,0 +1,96 @@
#!/bin/sh
# Author jjm2473@gmail.com
# Author Xiaobao(xiaobao@linkease.com)
ACTION=${1}
shift 1
ARCH="default"
IMAGE_NAME='default'
get_image() {
IMAGE_NAME=`uci get arcadia.@arcadia[0].image 2>/dev/null`
if [ -z "$IMAGE_NAME" -o "$IMAGE_NAME" == "default" ]; then
IMAGE_NAME="supermanito/arcadia:beta"
fi
}
do_install() {
get_image
echo "docker pull ${IMAGE_NAME}"
docker pull ${IMAGE_NAME}
docker rm -f arcadia
do_install_detail
}
do_install_detail() {
local hostnet=`uci get arcadia.@arcadia[0].hostnet 2>/dev/null`
local config=`uci get arcadia.@arcadia[0].config_path 2>/dev/null`
local port=`uci get arcadia.@arcadia[0].port 2>/dev/null`
local dev
if [ -z "$config" ]; then
echo "config path is empty!"
exit 1
fi
[ -z "$port" ] && port=5678
local cmd="docker run --restart=unless-stopped -d -v \"$config/config:/arcadia/config\" -v \"$config/log:/arcadia/log\" -v \"$config/scripts:/arcadia/scripts\" -v \"$config/repo:/arcadia/repo\" -v \"$config/raw:/arcadia/raw\" -v \"$config/tgbot:/arcadia/tgbot\" "
if [ "$hostnet" = 1 ]; then
cmd="$cmd\
--dns=127.0.0.1 \
--network=host "
else
cmd="$cmd\
--dns=172.17.0.1 \
-p $port:5678 "
fi
local tz="`uci get system.@system[0].zonename | sed 's/ /_/g'`"
[ -z "$tz" ] || cmd="$cmd -e TZ=$tz"
cmd="$cmd -v /mnt:/mnt"
mountpoint -q /mnt && cmd="$cmd:rslave"
cmd="$cmd --name arcadia \"$IMAGE_NAME\""
echo "$cmd"
eval "$cmd"
}
usage() {
echo "usage: $0 sub-command"
echo "where sub-command is one of:"
echo " install Install the arcadia"
echo " upgrade Upgrade the arcadia"
echo " rm/start/stop/restart Remove/Start/Stop/Restart the arcadia"
echo " status Arcadia status"
echo " port Arcadia port"
}
case ${ACTION} in
"install")
do_install
;;
"upgrade")
do_install
;;
"rm")
docker rm -f arcadia
;;
"start" | "stop" | "restart")
docker ${ACTION} arcadia
;;
"status")
docker ps --all -f 'name=^/arcadia$' --format '{{.State}}'
;;
"port")
docker ps --all -f 'name=^/arcadia$' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*->5678/tcp' | sed 's/0.0.0.0:\([0-9]*\)->.*/\1/'
;;
*)
usage
exit 1
;;
esac

View File

@ -2,7 +2,7 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.0.1-20231208
PKG_VERSION:=1.0.2-20241211
PKG_RELEASE:=
LUCI_TITLE:=LuCI support for bmtedge
@ -13,6 +13,14 @@ define Package/luci-app-bmtedge/conffiles
/etc/config/bmtedge
endef
# prerm
# postrm
define Package/luci-app-bmtedge/prerm
#!/bin/sh
/root/usr/libexec/istorec/bmtedge.sh rm
exit 0
endef
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature

View File

@ -23,10 +23,12 @@ bmtedge.blocks = function()
end
bmtedge.default_image = function()
local dockeramd64 = "registry.cn-shanghai.aliyuncs.com/nsp-prod-1/public1:lsy-iaas-amd64-latest"
local dockerarm64 = "registry.cn-shanghai.aliyuncs.com/nsp-prod-1/public1:lsy-iaas-arm64-latest"
if string.find(nixio.uname().machine, "x86_64") then
return "jinshanyun/jinshan-x86_64"
return dockeramd64
else
return "jinshanyun/jinshan-arm64"
return dockerarm64
end
end

View File

@ -21,10 +21,10 @@ local default_image = bmtedge_model.default_image()
o = s:option(Value, "image_name", translate("Image").."<b>*</b>")
o.rmempty = false
o.datatype = "string"
o:value("jinshanyun/jinshan-x86_64", "jinshanyun/jinshan-x86_64")
o:value("jinshanyun/jinshan-arm64", "jinshanyun/jinshan-arm64")
o:value("jinshanyun/jinshan-x86_64:v1.2", "jinshanyun/jinshan-x86_64:v1.2")
o:value("jinshanyun/jinshan-arm64:v2.2", "jinshanyun/jinshan-arm64:v2.2")
local dockeramd64 = "registry.cn-shanghai.aliyuncs.com/nsp-prod-1/public1:lsy-iaas-amd64-latest"
local dockerarm64 = "registry.cn-shanghai.aliyuncs.com/nsp-prod-1/public1:lsy-iaas-arm64-latest"
o:value(dockeramd64, dockeramd64)
o:value(dockerarm64, dockerarm64)
o.default = default_image
local default_uid = bmtedge_model.default_uid()

View File

@ -50,7 +50,7 @@ local uid = uci:get_first("bmtedge", "bmtedge", "uid", "")
return;
}
shown = true;
new QRCode(document.getElementById("qrimage"), "lsyK17032_"+"<%=uid%>");
new QRCode(document.getElementById("qrimage"), "lsyK18000_"+"<%=uid%>");
document.getElementById("winContainer").style.removeProperty('display');
};

View File

@ -25,17 +25,15 @@ do_install() {
docker rm -f bmtedge
local cmd="docker run --restart=unless-stopped -d \
--init \
--privileged \
--network=host \
--dns=127.0.0.1 \
--dns=223.5.5.5 \
--tmpfs /run \
--tmpfs /tmp \
-v \"$path:/data/ksc1\" \
-v \"$path/containerd:/var/lib/containerd\" \
-e ksc_datadir=\"/data/ksc1\" \
-v \"$path:/data/lsy_cloud\" \
-e ksc_datadir=\"/data/lsy_cloud\" \
-e ksc_net=\"$netdev\" \
-e ksc_machine_code=\"lsyK17032_$uid\" "
-e ksc_machine_code=\"lsyK18000_$uid\" "
local tz="`uci get system.@system[0].zonename | sed 's/ /_/g'`"
[ -z "$tz" ] || cmd="$cmd -e TZ=$tz"
@ -90,10 +88,10 @@ EOF
docker ${ACTION} bmtedge
;;
"status")
docker ps --all -f 'name=bmtedge' --format '{{.State}}'
docker ps --all -f 'name=^/bmtedge$' --format '{{.State}}'
;;
"port")
docker ps --all -f 'name=bmtedge' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*' | sed 's/0.0.0.0://'
docker ps --all -f 'name=^/bmtedge$' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*' | sed 's/0.0.0.0://'
;;
*)
usage

View File

@ -2,7 +2,7 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.0.3-20240113
PKG_VERSION:=1.0.3-20240822
PKG_RELEASE:=
LUCI_TITLE:=LuCI support for ChineseSubFinder

View File

@ -66,7 +66,7 @@ case ${ACTION} in
docker ${ACTION} chinesesubfinder
;;
"status")
docker ps --all -f 'name=chinesesubfinder' --format '{{.State}}'
docker ps --all -f 'name=^/chinesesubfinder$' --format '{{.State}}'
;;
"port")
uci -q get chinesesubfinder.@main[0].http_port 2>/dev/null

View File

@ -2,7 +2,7 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.0.1-20240117
PKG_VERSION:=1.0.1-20240822
PKG_RELEASE:=
LUCI_TITLE:=LuCI support for CloudDrive2

View File

@ -93,10 +93,10 @@ case ${ACTION} in
docker ${ACTION} clouddrive2
;;
"status")
docker ps --all -f 'name=clouddrive2' --format '{{.State}}'
docker ps --all -f 'name=^/clouddrive2$' --format '{{.State}}'
;;
"port")
docker ps --all -f 'name=clouddrive2' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*->19798/tcp' | sed 's/0.0.0.0:\([0-9]*\)->.*/\1/'
docker ps --all -f 'name=^/clouddrive2$' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*->19798/tcp' | sed 's/0.0.0.0:\([0-9]*\)->.*/\1/'
;;
*)
usage

View File

@ -2,7 +2,7 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.0.1-20231208
PKG_VERSION:=1.0.1-20240822
PKG_RELEASE:=
LUCI_TITLE:=LuCI support for CodeServer

View File

@ -72,10 +72,10 @@ case ${ACTION} in
docker ${ACTION} codeserver
;;
"status")
docker ps --all -f 'name=codeserver' --format '{{.State}}'
docker ps --all -f 'name=^/codeserver$' --format '{{.State}}'
;;
"port")
docker ps --all -f 'name=codeserver' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*' | sed 's/0.0.0.0://'
docker ps --all -f 'name=^/codeserver$' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*' | sed 's/0.0.0.0://'
;;
"git-config")
docker exec codeserver git config --global user.name "${1}"

View File

@ -2,7 +2,7 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.0.0-20221212
PKG_VERSION:=1.0.0-20240822
PKG_RELEASE:=
LUCI_TITLE:=LuCI support for DrawIO

View File

@ -59,10 +59,10 @@ case ${ACTION} in
cd $config && docker-compose ${ACTION}
;;
"status")
docker ps --all -f 'name=linkease-drawio_drawio_1' --format '{{.State}}'
docker ps --all -f 'name=^/linkease-drawio_drawio_1$' --format '{{.State}}'
;;
"port")
docker ps --all -f 'name=linkease-drawio_drawio_1' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*' | sed 's/0.0.0.0://'
docker ps --all -f 'name=^/linkease-drawio_drawio_1$' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*' | sed 's/0.0.0.0://'
;;
*)
usage

View File

@ -2,7 +2,7 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.0.3-20231208
PKG_VERSION:=1.0.3-20240822
PKG_RELEASE:=
LUCI_TITLE:=LuCI support for Emby

View File

@ -81,10 +81,10 @@ case ${ACTION} in
docker ${ACTION} emby
;;
"status")
docker ps --all -f 'name=emby' --format '{{.State}}'
docker ps --all -f 'name=^/emby$' --format '{{.State}}'
;;
"port")
docker ps --all -f 'name=emby' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*->8096/tcp' | sed 's/0.0.0.0:\([0-9]*\)->.*/\1/'
docker ps --all -f 'name=^/emby$' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*->8096/tcp' | sed 's/0.0.0.0:\([0-9]*\)->.*/\1/'
;;
*)
usage

View File

@ -2,7 +2,7 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.0.0-20221212
PKG_VERSION:=1.0.0-20240822
PKG_RELEASE:=
LUCI_TITLE:=LuCI support for Excalidraw

View File

@ -60,10 +60,10 @@ case ${ACTION} in
cd $config && docker-compose ${ACTION}
;;
"status")
docker ps --all -f 'name=linkease-excalidraw_frontend_1' --format '{{.State}}'
docker ps --all -f 'name=^/linkease-excalidraw_frontend_1$' --format '{{.State}}'
;;
"port")
docker ps --all -f 'name=linkease-excalidraw_frontend_1' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*' | sed 's/0.0.0.0://'
docker ps --all -f 'name=^/linkease-excalidraw_frontend_1$' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*' | sed 's/0.0.0.0://'
;;
*)
usage

View File

@ -2,7 +2,7 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.0.2-20231208
PKG_VERSION:=1.0.2-20240822
PKG_RELEASE:=
LUCI_TITLE:=LuCI support for FeiShuVpn

View File

@ -62,7 +62,7 @@ case ${ACTION} in
docker ${ACTION} feishuvpn
;;
"status")
docker ps --all -f 'name=feishuvpn' --format '{{.State}}'
docker ps --all -f 'name=^/feishuvpn$' --format '{{.State}}'
;;
"port")
echo 9091

View File

@ -2,7 +2,7 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.0.3-20240304
PKG_VERSION:=1.0.3-20240822
PKG_RELEASE:=
LUCI_TITLE:=LuCI support for Gogs

View File

@ -67,7 +67,7 @@ case ${ACTION} in
docker ${ACTION} gogs
;;
"status")
docker ps --all -f 'name=gogs' --format '{{.State}}'
docker ps --all -f 'name=^/gogs$' --format '{{.State}}'
;;
"port")
uci -q get gogs.@main[0].http_port 2>/dev/null

View File

@ -2,7 +2,7 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.1.2-20240105
PKG_VERSION:=1.1.2-20240822
PKG_RELEASE:=
LUCI_TITLE:=LuCI support for heimdall

View File

@ -73,13 +73,13 @@ case ${ACTION} in
docker ${ACTION} heimdall
;;
"status")
docker ps --all -f 'name=heimdall' --format '{{.State}}'
docker ps --all -f 'name=^/heimdall$' --format '{{.State}}'
;;
"port")
docker ps --all -f 'name=heimdall' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*->80/tcp' | sed 's/0.0.0.0:\([0-9]*\)->.*/\1/'
docker ps --all -f 'name=^/heimdall$' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*->80/tcp' | sed 's/0.0.0.0:\([0-9]*\)->.*/\1/'
;;
"https_port")
docker ps --all -f 'name=heimdall' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*->443/tcp' | sed 's/0.0.0.0:\([0-9]*\)->.*/\1/'
docker ps --all -f 'name=^/heimdall$' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*->443/tcp' | sed 's/0.0.0.0:\([0-9]*\)->.*/\1/'
;;
*)
usage

View File

@ -2,7 +2,7 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.1.2-20231208
PKG_VERSION:=1.1.2-20240822
PKG_RELEASE:=
LUCI_TITLE:=LuCI support for homeassistant

View File

@ -74,10 +74,10 @@ case ${ACTION} in
docker ${ACTION} homeassistant
;;
"status")
docker ps --all -f 'name=homeassistant' --format '{{.State}}'
docker ps --all -f 'name=^/homeassistant$' --format '{{.State}}'
;;
"port")
docker ps --all -f 'name=homeassistant' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*' | sed 's/0.0.0.0://'
docker ps --all -f 'name=^/homeassistant$' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*' | sed 's/0.0.0.0://'
;;
"hacs-install")
do_hacs_install

View File

@ -2,7 +2,7 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.0.2-20231208
PKG_VERSION:=1.0.2-20240822
PKG_RELEASE:=
LUCI_TITLE:=LuCI support for HTReader

View File

@ -74,10 +74,10 @@ case ${ACTION} in
docker ${ACTION} htreader
;;
"status")
docker ps --all -f 'name=htreader' --format '{{.State}}'
docker ps --all -f 'name=^/htreader$' --format '{{.State}}'
;;
"port")
docker ps --all -f 'name=htreader' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*->9060/tcp' | sed 's/0.0.0.0:\([0-9]*\)->.*/\1/'
docker ps --all -f 'name=^/htreader$' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*->9060/tcp' | sed 's/0.0.0.0:\([0-9]*\)->.*/\1/'
;;
*)
usage

View File

@ -0,0 +1,24 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.1.7-20241211
PKG_RELEASE:=
LUCI_TITLE:=LuCI support for istoredup
LUCI_PKGARCH:=all
LUCI_DEPENDS:=+lsblk +docker +luci-lib-taskd +vmease
define Package/luci-app-istoredup/conffiles
/etc/config/istoredup
endef
define Package/luci-app-istoredup/prerm
#!/bin/sh
/usr/libexec/istorec/istoredup.sh stop
exit 0
endef
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature

View File

@ -0,0 +1,9 @@
module("luci.controller.istoredup", package.seeall)
function index()
entry({"admin", "services", "istoredup"}, alias("admin", "services", "istoredup", "config"), _("iStoreDup"), 30).dependent = true
entry({"admin", "services", "istoredup", "config"}, cbi("istoredup/config"), _("Config"), 10).leaf = true
entry({"admin", "services", "istoredup", "tool"}, form("istoredup/tool"), _("Tool"), 30).leaf = true
entry({"admin", "services", "istoredup", "console"}, form("istoredup/console"), _("Console"), 50).leaf = true
end

View File

@ -0,0 +1,49 @@
--[[
LuCI - Lua Configuration Interface
]]--
local taskd = require "luci.model.tasks"
local docker = require "luci.docker"
local istoredup_model = require "luci.model.istoredup"
local m, s, o
m = taskd.docker_map("istoredup", "istoredup", "/usr/libexec/istorec/istoredup.sh",
translate("iStoreDup"),
translate("A duplica of iStoreOS.")
.. translate("Official website:") .. ' <a href=\"https://www.istoreos.com/\" target=\"_blank\">https://www.istoreos.com/</a>')
local dk = docker.new({socket_path="/var/run/docker.sock"})
local dockerd_running = dk:_ping().code == 200
local docker_info = dockerd_running and dk:info().body or {}
local docker_aspace = 0
if docker_info.DockerRootDir then
local statvfs = nixio.fs.statvfs(docker_info.DockerRootDir)
docker_aspace = statvfs and (statvfs.bavail * statvfs.bsize) or 0
end
s = m:section(SimpleSection, translate("Service Status"), translate("iStoreDup status:"))
s:append(Template("istoredup/status"))
s = m:section(TypedSection, "istoredup", translate("Setup"),
(docker_aspace < 2147483648 and
(translate("The free space of Docker is less than 2GB, which may cause the installation to fail.")
.. "<br>") or "") .. translate("The following parameters will only take effect during installation or upgrade:"))
s.addremove=false
s.anonymous=true
o = s:option(Value, "image_name", translate("Image").."<b>*</b>")
o.rmempty = false
o.datatype = "string"
o:value("linkease/istoreduprk35xx:latest", "linkease/istoreduprk35xx:latest")
o:value("linkease/istoredupx86_64:latest", "linkease/istoredupx86_64:latest")
if "x86_64" == docker_info.Architecture then
o.default = "linkease/istoredupx86_64:latest"
else
o.default = "linkease/istoreduprk35xx:latest"
end
o = s:option(Value, "time_zone", translate("Timezone"))
o.datatype = "string"
o:value("Asia/Shanghai", "Asia/Shanghai")
return m

View File

@ -0,0 +1,116 @@
--[[
LuCI - Lua Configuration Interface
]]--
require "luci.util"
local docker = require "luci.model.docker"
local dk = docker.new()
local container_name = "istoredup"
local m, s, o
local images, networks, container_info, res
res = dk.containers:inspect({name = container_name})
if res.code < 300 then
container_info = res.body
else
return
end
local cmd_docker = luci.util.exec("command -v docker"):match("^.+docker") or nil
local cmd_ttyd = luci.util.exec("command -v ttyd"):match("^.+ttyd") or nil
if cmd_docker and cmd_ttyd and container_info.State.Status == "running" then
local cmd = "/bin/bash"
local uid
m=SimpleForm("Console", "", translate("Only works in LAN"))
m.submit = false
m.reset = false
s = m:section(SimpleSection)
o = s:option(Value, "command", translate("Command"))
o:value("/bin/sh", "/bin/sh")
o:value("/bin/ash", "/bin/ash")
o:value("/bin/bash", "/bin/bash")
o.default = "/bin/bash"
o.forcewrite = true
o.write = function(self, section, value)
cmd = value
end
o = s:option(Value, "uid", translate("UID"))
o.forcewrite = true
o.write = function(self, section, value)
uid = value
end
o = s:option(Button, "connect")
o.render = function(self, section, scope)
self.inputstyle = "add"
self.title = " "
self.inputtitle = translate("Connect")
Button.render(self, section, scope)
end
o.write = function(self, section)
local cmd_docker = luci.util.exec("command -v docker"):match("^.+docker") or nil
local cmd_ttyd = luci.util.exec("command -v ttyd"):match("^.+ttyd") or nil
if not cmd_docker or not cmd_ttyd or cmd_docker:match("^%s+$") or cmd_ttyd:match("^%s+$")then
return
end
local pid = luci.util.trim(luci.util.exec("netstat -lnpt | grep :7682 | grep ttyd | tr -s ' ' | cut -d ' ' -f7 | cut -d'/' -f1"))
if pid and pid ~= "" then
luci.util.exec("kill -9 " .. pid)
end
local hosts
local uci = require "luci.model.uci".cursor()
local remote = uci:get_bool("dockerd", "globals", "remote_endpoint") or false
local host = nil
local port = nil
local socket = nil
if remote then
host = uci:get("dockerd", "globals", "remote_host") or nil
port = uci:get("dockerd", "globals", "remote_port") or nil
else
socket = uci:get("dockerd", "globals", "socket_path") or "/var/run/docker.sock"
end
if remote and host and port then
hosts = host .. ':'.. port
elseif socket then
hosts = socket
else
return
end
if uid and uid ~= "" then
uid = "-u " .. uid
else
uid = ""
end
local start_cmd = string.format('%s -d 2 --once -p 7682 %s -H "unix://%s" exec -it %s %s %s&', cmd_ttyd, cmd_docker, hosts, uid, container_name, cmd)
os.execute(start_cmd)
m.children[#m.children] = nil
s = m:section(SimpleSection)
o = s:option(DummyValue, "console")
o.container_id = container_id
o.template = container_name .. "/console"
end
else
m=SimpleForm("Console", "", translate("iStoreDup is not running"))
m.submit = false
m.reset = false
s = m:section(SimpleSection)
end
return m

View File

@ -0,0 +1,41 @@
--[[
LuCI - Lua Configuration Interface
]]--
local http = require 'luci.http'
m=SimpleForm("Tools")
m.submit = false
m.reset = false
s = m:section(SimpleSection)
o = s:option(Value, "action", translate("Action").."<b>*</b>")
o.rmempty = false
o.datatype = "string"
o:value("show-ip", "show-ip")
o.default = "show-ip"
local t=Template("istoredup/tool")
m:append(t)
local btn_do = s:option(Button, "_do")
btn_do.render = function(self, section, scope)
self.inputstyle = "add"
self.title = " "
self.inputtitle = translate("Execute")
Button.render(self, section, scope)
end
btn_do.write = function(self, section, value)
local action = m:get(section, "action")
if action == "show-ip" then
local cmd = string.format("/usr/libexec/istorec/istoredup.sh %s", action)
cmd = "/etc/init.d/tasks task_add istoredup " .. luci.util.shellquote(cmd) .. " >/dev/null 2>&1"
os.execute(cmd)
t.show_log_taskid = "istoredup"
end
end
return m

View File

@ -0,0 +1,55 @@
local util = require "luci.util"
local jsonc = require "luci.jsonc"
local emby = {}
emby.blocks = function()
local f = io.popen("lsblk -s -f -b -o NAME,FSSIZE,MOUNTPOINT --json", "r")
local vals = {}
if f then
local ret = f:read("*all")
f:close()
local obj = jsonc.parse(ret)
for _, val in pairs(obj["blockdevices"]) do
local fsize = val["fssize"]
if fsize ~= nil and string.len(fsize) > 10 and val["mountpoint"] then
-- fsize > 1G
vals[#vals+1] = val["mountpoint"]
end
end
end
return vals
end
emby.home = function()
local uci = require "luci.model.uci".cursor()
local home_dirs = {}
home_dirs["main_dir"] = uci:get_first("quickstart", "main", "main_dir", "/root")
home_dirs["Configs"] = uci:get_first("quickstart", "main", "conf_dir", home_dirs["main_dir"].."/Configs")
home_dirs["Public"] = uci:get_first("quickstart", "main", "pub_dir", home_dirs["main_dir"].."/Public")
home_dirs["Downloads"] = uci:get_first("quickstart", "main", "dl_dir", home_dirs["Public"].."/Downloads")
home_dirs["Caches"] = uci:get_first("quickstart", "main", "tmp_dir", home_dirs["main_dir"].."/Caches")
return home_dirs
end
emby.find_paths = function(blocks, home_dirs, path_name)
local default_path = ''
local configs = {}
default_path = home_dirs[path_name] .. "/iStoreDup"
if #blocks == 0 then
table.insert(configs, default_path)
else
for _, val in pairs(blocks) do
table.insert(configs, val .. "/" .. path_name .. "/iStoreDup")
end
local without_conf_dir = "/root/" .. path_name .. "/iStoreDup"
if default_path == without_conf_dir then
default_path = configs[1]
end
end
return configs, default_path
end
return emby

View File

@ -0,0 +1,6 @@
<div class="cbi-map">
<iframe id="terminal" style="width: 100%; min-height: 600px; border: none; border-radius: 3px;"></iframe>
</div>
<script type="text/javascript">
document.getElementById("terminal").src = "http://" + window.location.hostname + ":7682";
</script>

View File

@ -0,0 +1,31 @@
<%
local util = require "luci.util"
local container_status = util.trim(util.exec("/usr/libexec/istorec/istoredup.sh status"))
local container_install = (string.len(container_status) > 0)
local container_running = container_status == "running"
-%>
<div class="cbi-value">
<label class="cbi-value-title"><%:Status%></label>
<div class="cbi-value-field">
<% if container_running then %>
<button class="cbi-button cbi-button-success" disabled="true"><%:iStoreDup is running%></button>
<% else %>
<button class="cbi-button cbi-button-negative" disabled="true"><%:iStoreDup is not running%></button>
<% end %>
</div>
</div>
<%
if container_running then
local port=util.trim(util.exec("/usr/libexec/istorec/istoredup.sh port"))
if port == "" then
port="error"
end
-%>
<div class="cbi-value cbi-value-last">
<label class="cbi-value-title">&nbsp;</label>
<div class="cbi-value-field">
<input type="button" class="btn cbi-button cbi-button-apply" name="start" value="<%:Open the iStoreDup%>" onclick="window.open('http://<%=port%>/', '_blank')">
</div>
</div>
<% end %>

View File

@ -0,0 +1,11 @@
<%+tasks/embed%>
<script>
window.addEventListener("load", function(){
const taskd = window.taskd;
<% if self.show_log_taskid then -%>
taskd.show_log("<%=self.show_log_taskid%>");
<%- end %>
});
</script>

View File

@ -0,0 +1,48 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8"
msgid "Official website:"
msgstr "官方网站:"
msgid "A duplica of iStoreOS."
msgstr "iStoreOS 的分身,可以把风险高的软件安装到分身里面,出问题不影响到主系统。"
msgid "Service Status"
msgstr "服务状态"
msgid "iStoreDup status:"
msgstr "iStoreDup 的状态信息如下:"
msgid "Setup"
msgstr "安装配置"
msgid "The following parameters will only take effect during installation or upgrade:"
msgstr "以下参数只在安装或者升级时才会生效:"
msgid "Status"
msgstr "状态"
msgid "iStoreDup is running"
msgstr "iStoreDup 运行中"
msgid "iStoreDup is not running"
msgstr "iStoreDup 未运行"
msgid "Open the iStoreDup"
msgstr "打开 iStoreDup"
msgid "Tool"
msgstr "操作"
msgid "Console"
msgstr "控制台"
msgid "Only works in LAN"
msgstr "只在内网环境下工作。"
msgid "Execute"
msgstr "执行"
msgid "Timezone"
msgstr "时区"

View File

@ -0,0 +1 @@
config istoredup

View File

@ -0,0 +1,98 @@
#!/bin/sh
ACTION=${1}
shift 1
do_install() {
local IMAGE_NAME=`uci get istoredup.@istoredup[0].image_name 2>/dev/null`
local arch=`uname -m`
if [ "$arch" = "x86_64" -o "$arch" = "aarch64" ]; then
echo "${arch} supported"
else
echo "Unsupported ${arch} NOW"
sleep 10
exit 1
fi
if [ -z ${IMAGE_NAME} ]; then
if [ "$arch" = "x86_64" ]; then
IMAGE_NAME=linkease/istoredupx86_64:latest
else
IMAGE_NAME=linkease/istoreduprk35xx:latest
fi
fi
echo "docker pull ${IMAGE_NAME}"
docker pull ${IMAGE_NAME}
docker rm -f istoredup
local hasvlan=`docker network inspect dsm-net -f '{{.Name}}' 2>/dev/null`
if [ ! "$hasvlan" = "dsm-net" ]; then
docker network create -o com.docker.network.bridge.name=dsm-br --driver=bridge dsm-net
fi
local mask=`ubus call network.interface.lan status | jsonfilter -e '@["ipv4-address"][0].mask'`
local cmd="docker run --restart=unless-stopped -d \
-h iStoreDuplica \
-v /var/run/vmease:/host/run/vmease \
--privileged \
--net=dsm-net \
--sysctl net.netfilter.nf_conntrack_acct=1 \
--sysctl net.ipv4.conf.all.forwarding=1 \
--dns=172.17.0.1 "
cmd="$cmd -v /mnt:/mnt"
mountpoint -q /mnt && cmd="$cmd:rslave"
cmd="$cmd --stop-timeout 120 --name istoredup \"$IMAGE_NAME\""
echo "$cmd"
eval "$cmd"
echo "wait running"
sleep 5
echo "done"
}
usage() {
echo "usage: $0 sub-command"
echo "where sub-command is one of:"
echo " install Install the istoredup"
echo " upgrade Upgrade the istoredup"
echo " rm/start/stop/restart Remove/Start/Stop/Restart the istoredup"
echo " status iStoreDup status"
echo " port iStoreDup port"
}
case ${ACTION} in
"install")
do_install
;;
"upgrade")
do_install
;;
"rm")
docker rm -f istoredup
;;
"start" | "stop" | "restart")
docker ${ACTION} istoredup
;;
"status")
docker ps --all -f 'name=^/istoredup$' --format '{{.State}}'
;;
"port")
docker exec istoredup ip -f inet addr show br-lan|sed -En -e 's/.*inet ([0-9.]+).*/\1/p'
;;
"show-ip")
IP=`docker exec istoredup ip -f inet addr show br-lan|sed -En -e 's/.*inet ([0-9.]+).*/\1/p'`
if [ -z "$IP" ]; then
echo "reset ip"
docker exec istoredup /etc/init.d/setupvmease start
sleep 5
IP=`docker exec istoredup ip -f inet addr show br-lan|sed -En -e 's/.*inet ([0-9.]+).*/\1/p'`
fi
echo $IP
;;
*)
usage
exit 1
;;
esac

View File

@ -0,0 +1,18 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.0.6-20240822
PKG_RELEASE:=
LUCI_TITLE:=LuCI support for 1Panel
LUCI_PKGARCH:=all
LUCI_DEPENDS:=+lsblk +zoneinfo-asia +docker +luci-lib-taskd +luci-lib-docker
define Package/luci-app-istorepanel/conffiles
/etc/config/istorepanel
endef
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature

View File

@ -0,0 +1,7 @@
module("luci.controller.istorepanel", package.seeall)
function index()
entry({"admin", "services", "istorepanel"}, alias("admin", "services", "istorepanel", "config"), _("1Panel"), 30).dependent = true
entry({"admin", "services", "istorepanel", "config"}, cbi("istorepanel"))
end

View File

@ -0,0 +1,76 @@
--[[
LuCI - Lua Configuration Interface
]]--
local taskd = require "luci.model.tasks"
local docker = require "luci.docker"
local istorepanel_model = require "luci.model.istorepanel"
local m, s, o
m = taskd.docker_map("istorepanel", "istorepanel", "/usr/libexec/istorec/istorepanel.sh",
translate("1Panel"),
translate("1Panel is the new generation Linux server maintenance panel.")
.. translate("Official website:") .. ' <a href=\"https://1panel.cn/\" target=\"_blank\">https://1panel.cn/</a>')
local dk = docker.new({socket_path="/var/run/docker.sock"})
local dockerd_running = dk:_ping().code == 200
local docker_info = dockerd_running and dk:info().body or {}
local docker_aspace = 0
if docker_info.DockerRootDir then
local statvfs = nixio.fs.statvfs(docker_info.DockerRootDir)
docker_aspace = statvfs and (statvfs.bavail * statvfs.bsize) or 0
end
s = m:section(SimpleSection, translate("Service Status"), translate("1Panel status:"))
s:append(Template("istorepanel/status"))
s = m:section(TypedSection, "main", translate("Setup"),
(docker_aspace < 2147483648 and
(translate("The free space of Docker is less than 2GB, which may cause the installation to fail.")
.. "<br>") or "") .. translate("The following parameters will only take effect during installation or upgrade:"))
s.addremove=false
s.anonymous=true
o = s:option(Value, "port", translate("Port").."<b>*</b>")
o.default = "8063"
o.datatype = "port"
o:depends("hostnet", 0)
o = s:option(Value, "username", "username")
o.datatype = "string"
o.default = '1panel'
o = s:option(Value, "password", "password")
o.password = true
o.datatype = "string"
o.default = "password"
o = s:option(Value, "ver", "version")
o.datatype = "string"
o:value("v1.10.10-lts", "v1.10.10-lts")
o:value("v1.10.11-lts", "v1.10.11-lts")
o.default = 'v1.10.11-lts'
o = s:option(Value, "image_name", translate("Image").."<b>*</b>")
o.rmempty = false
o.datatype = "string"
o:value("linkease/istorepanel:latest", "linkease/istorepanel:latest")
o.default = "linkease/istorepanel:latest"
local blocks = istorepanel_model.blocks()
local home = istorepanel_model.home()
o = s:option(Value, "config_path", translate("Config path").."<b>*</b>")
o.rmempty = false
o.datatype = "string"
local paths, default_path = istorepanel_model.find_paths(blocks, home, "Configs")
for _, val in pairs(paths) do
o:value(val, val)
end
o.default = default_path
o = s:option(Flag, "include_host", translate("Include root path"))
o.rmempty = false
return m

View File

@ -0,0 +1,55 @@
local util = require "luci.util"
local jsonc = require "luci.jsonc"
local istorepanel = {}
istorepanel.blocks = function()
local f = io.popen("lsblk -s -f -b -o NAME,FSSIZE,MOUNTPOINT --json", "r")
local vals = {}
if f then
local ret = f:read("*all")
f:close()
local obj = jsonc.parse(ret)
for _, val in pairs(obj["blockdevices"]) do
local fsize = val["fssize"]
if fsize ~= nil and string.len(fsize) > 10 and val["mountpoint"] then
-- fsize > 1G
vals[#vals+1] = val["mountpoint"]
end
end
end
return vals
end
istorepanel.home = function()
local uci = require "luci.model.uci".cursor()
local home_dirs = {}
home_dirs["main_dir"] = uci:get_first("quickstart", "main", "main_dir", "/root")
home_dirs["Configs"] = uci:get_first("quickstart", "main", "conf_dir", home_dirs["main_dir"].."/Configs")
home_dirs["Public"] = uci:get_first("quickstart", "main", "pub_dir", home_dirs["main_dir"].."/Public")
home_dirs["Downloads"] = uci:get_first("quickstart", "main", "dl_dir", home_dirs["Public"].."/Downloads")
home_dirs["Caches"] = uci:get_first("quickstart", "main", "tmp_dir", home_dirs["main_dir"].."/Caches")
return home_dirs
end
istorepanel.find_paths = function(blocks, home_dirs, path_name)
local default_path = ''
local configs = {}
default_path = home_dirs[path_name] .. "/1Panel"
if #blocks == 0 then
table.insert(configs, default_path)
else
for _, val in pairs(blocks) do
table.insert(configs, val .. "/" .. path_name .. "/1Panel")
end
local without_conf_dir = "/root/" .. path_name .. "/1Panel"
if default_path == without_conf_dir then
default_path = configs[1]
end
end
return configs, default_path
end
return istorepanel

View File

@ -0,0 +1,31 @@
<%
local util = require "luci.util"
local container_status = util.trim(util.exec("/usr/libexec/istorec/istorepanel.sh status"))
local container_install = (string.len(container_status) > 0)
local container_running = container_status == "running"
-%>
<div class="cbi-value">
<label class="cbi-value-title"><%:Status%></label>
<div class="cbi-value-field">
<% if container_running then %>
<button class="cbi-button cbi-button-success" disabled="true"><%:1Panel is running%></button>
<% else %>
<button class="cbi-button cbi-button-negative" disabled="true"><%:1Panel is not running%></button>
<% end %>
</div>
</div>
<%
if container_running then
local port=util.trim(util.exec("/usr/libexec/istorec/istorepanel.sh port"))
if port == "" then
port="10086"
end
-%>
<div class="cbi-value cbi-value-last">
<label class="cbi-value-title">&nbsp;</label>
<div class="cbi-value-field">
<input type="button" class="btn cbi-button cbi-button-apply" name="start" value="<%:Open 1Panel%>" onclick="window.open('http://'+location.hostname+':<%=port%>/entrance', '_blank')">
</div>
</div>
<% end %>

View File

@ -0,0 +1,44 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8"
msgid "Official website:"
msgstr "官方网站:"
msgid "1Panel is the new generation Linux server maintenance panel."
msgstr "1Panel 是新一代的 Linux 服务器运维管理面板"
msgid "Config path"
msgstr "配置文件路径"
msgid "Port"
msgstr "端口"
msgid "Service Status"
msgstr "服务状态"
msgid "1Panel status:"
msgstr "1Panel 的状态信息如下:"
msgid "Setup"
msgstr "安装配置"
msgid "The following parameters will only take effect during installation or upgrade:"
msgstr "以下参数只在安装或者升级时才会生效:"
msgid "Status"
msgstr "状态"
msgid "1Panel is running"
msgstr "1Panel 运行中"
msgid "1Panel is not running"
msgstr "1Panel 未运行"
msgid "Open 1Panel"
msgstr "打开 1Panel"
msgid "The free space of Docker is less than 2GB, which may cause the installation to fail."
msgstr "Docker 可用空间已不足2GB可能导致安装失败。"
msgid "Please make sure there has enough space"
msgstr "请确保有足够空间"

View File

@ -0,0 +1,8 @@
config main
option 'port' '10086'
# option 'config_path' ''
# option 'ver' 'v1.10.10-lts'
# option 'entrance' 'entrance'
# option 'username' '1panel'
# option 'password' 'password'

View File

@ -0,0 +1,124 @@
#!/bin/sh
# Author Xiaobao(xiaobao@linkease.com)
ACTION=${1}
shift 1
do_install() {
local port=`uci get istorepanel.@main[0].port 2>/dev/null`
local image_name=`uci get istorepanel.@main[0].image_name 2>/dev/null`
local config=`uci get istorepanel.@main[0].config_path 2>/dev/null`
local entrance=`uci get istorepanel.@main[0].entrance 2>/dev/null`
local username=`uci get istorepanel.@main[0].username 2>/dev/null`
local password=`uci get istorepanel.@main[0].password 2>/dev/null`
local ver=`uci get istorepanel.@main[0].ver 2>/dev/null`
local include_host=`uci get istorepanel.@main[0].include_host 2>/dev/null`
if [ -z "$config" ]; then
echo "config path is empty!"
exit 1
fi
[ -z "$port" ] && port=10086
[ -z "$ver" ] && ver='v1.10.10-lts'
[ -z "$username" ] && username='1panel'
[ -z "$password" ] && password='password'
[ -z "$entrance" ] && entrance='entrance'
mkdir -p $config
cat > $config/env <<EOF
export PANEL_BASE_DIR=${config}
export PANEL_PORT=${port}
export DEFAULT_ENTRANCE=${entrance}
export DEFAULT_USERNAME=${username}
export DEFAULT_PASSWORD=${password}
export PANELVER=${ver}
EOF
[ -z "$image_name" ] && image_name="linkease/istorepanel:latest"
echo "docker pull ${image_name}"
docker pull ${image_name}
docker rm -f istorepanel
if [ ! -f "/tmp/localtime" ]; then
/etc/init.d/system reload
fi
local cmd="docker run --restart=unless-stopped -d -h 1PanelServer \
--cgroupns=host \
--cap-add SYS_ADMIN \
--tmpfs /tmp \
--network host \
-v /sys/fs/cgroup:/sys/fs/cgroup \
-v /var/run:/var2/run \
-v \"$config:/iStorePanel\" "
cmd="$cmd\
--dns=172.17.0.1 \
--dns=223.5.5.5 "
if [ "$include_host" = "1" ]; then
cmd="$cmd -v \"/:/ahost\" "
fi
local tz="`uci get system.@system[0].zonename | sed 's/ /_/g'`"
[ -z "$tz" ] || cmd="$cmd -e TZ=$tz"
cmd="$cmd -v /mnt:/mnt"
mountpoint -q /mnt && cmd="$cmd:rslave"
cmd="$cmd --name istorepanel \"$image_name\""
echo "$cmd"
eval "$cmd"
echo "Installing 1panel"
for b in {1..30}
do
sleep 3
docker_status=`docker ps --all -f 'name=^/istorepanel$' --format '{{.State}}'`
if [[ $docker_status == *running* ]]; then
docker exec istorepanel /app/reinstall.sh
echo "Installed OK, waiting 10s for running"
sleep 10
break;
else
echo "istorepanel is not running, wait..."
fi
done
}
usage() {
echo "usage: $0 sub-command"
echo "where sub-command is one of:"
echo " install Install the istorepanel"
echo " upgrade Upgrade the istorepanel"
echo " rm/start/stop/restart Remove/Start/Stop/Restart the istorepanel"
echo " status 1Panel status"
echo " port 1Panel port"
}
case ${ACTION} in
"install")
do_install
;;
"upgrade")
do_install
;;
"rm")
docker rm -f istorepanel
;;
"start" | "stop" | "restart")
docker ${ACTION} istorepanel
;;
"status")
docker ps --all -f 'name=^/istorepanel$' --format '{{.State}}'
;;
"port")
echo `uci get istorepanel.@main[0].port 2>/dev/null`
;;
*)
usage
exit 1
;;
esac

View File

@ -2,7 +2,7 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.0.2-20231208
PKG_VERSION:=1.0.2-20240822
PKG_RELEASE:=
LUCI_TITLE:=LuCI support for ITTools

View File

@ -56,10 +56,10 @@ case ${ACTION} in
docker ${ACTION} ittools
;;
"status")
docker ps --all -f 'name=ittools' --format '{{.State}}'
docker ps --all -f 'name=^/ittools$' --format '{{.State}}'
;;
"port")
docker ps --all -f 'name=ittools' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*->9070/tcp' | sed 's/0.0.0.0:\([0-9]*\)->.*/\1/'
docker ps --all -f 'name=^/ittools$' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*->9070/tcp' | sed 's/0.0.0.0:\([0-9]*\)->.*/\1/'
;;
*)
usage

View File

@ -2,7 +2,7 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.1.1-20231208
PKG_VERSION:=1.1.1-20240822
PKG_RELEASE:=
LUCI_TITLE:=LuCI support for jackett

View File

@ -76,10 +76,10 @@ case ${ACTION} in
docker ${ACTION} jackett
;;
"status")
docker ps --all -f 'name=jackett' --format '{{.State}}'
docker ps --all -f 'name=^/jackett$' --format '{{.State}}'
;;
"port")
docker ps --all -f 'name=jackett' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*' | sed 's/0.0.0.0://'
docker ps --all -f 'name=^/jackett$' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*' | sed 's/0.0.0.0://'
;;
*)
usage

View File

@ -2,7 +2,7 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.1.10-20240224
PKG_VERSION:=1.2.0-20240822
PKG_RELEASE:=
LUCI_TITLE:=LuCI support for jellyfin

View File

@ -10,7 +10,7 @@ m = taskd.docker_map("jellyfin", "jellyfin", "/usr/libexec/istorec/jellyfin.sh",
translate("Jellyfin"),
translate("Jellyfin is the volunteer-built media solution that puts you in control of your media. Stream to any device from your own server, with no strings attached. Your media, your server, your way.")
.. translate("Official website:") .. ' <a href=\"https://jellyfin.org/\" target=\"_blank\">https://jellyfin.org/</a>'
.. "<dl><dt>" .. translate("The following models support hardware transcoding without configuration in Jellyfin:") .. "</dt>"
.. "<dl><dt>" .. translate("When using the default image, the following models support hardware transcoding without configuration in Jellyfin:") .. "</dt>"
.. "<dd>- Easepi ARS2</dd>"
.. "<dd>- " .. translate("RK35xx series (e.g. R6S, R5S, R68s, R66s, H28K, etc.) with iStoreOS firmware (version 20221123 and above). Other firmwares require MPP and RGA to be turned on, and are not guaranteed to be available.") .. "</dd>"
.. "<dt>" .. translate("The following models may support hardware transcoding by referring to the official Jellyfin documentation:") .. "</dt>"
@ -27,6 +27,19 @@ s = m:section(TypedSection, "jellyfin", translate("Setup"),
s.addremove=false
s.anonymous=true
o = s:option(Value, "image", translate("Image"))
o.datatype = "string"
o:value("", translate("Default"))
if luci.sys.call("grep -q 'rockchip,' /proc/device-tree/compatible 2>/dev/null") == 0 then
o:value("jjm2473/jellyfin-mpp", "jjm2473/jellyfin-mpp")
o:value("nyanmisaka/jellyfin:latest-rockchip", "nyanmisaka/jellyfin:latest-rockchip")
end
o:value("jellyfin/jellyfin", "jellyfin/jellyfin")
o:value("linuxserver/jellyfin", "linuxserver/jellyfin")
if luci.sys.call("uname -m |grep -qw x86_64") == 0 then
o:value("nyanmisaka/jellyfin", "nyanmisaka/jellyfin")
end
o = s:option(Flag, "hostnet", translate("Host network"), translate("Jellyfin running in host network, for DLNA application, port is always 8096 if enabled"))
o.default = 0
o.rmempty = false

View File

@ -7,8 +7,8 @@ msgstr "官方网站:"
msgid "Jellyfin is the volunteer-built media solution that puts you in control of your media. Stream to any device from your own server, with no strings attached. Your media, your server, your way."
msgstr "Jellyfin 是志愿者构建的媒体解决方案,可让您控制自己的电影等媒体,并不受任何限制地让您从各种设备去观看您的媒体。"
msgid "The following models support hardware transcoding without configuration in Jellyfin:"
msgstr "以下机型无需在Jellyfin配置即支持硬件转码"
msgid "When using the default image, the following models support hardware transcoding without configuration in Jellyfin:"
msgstr "当使用默认镜像时以下机型无需在Jellyfin配置即支持硬件转码"
msgid "RK35xx series (e.g. R6S, R5S, R68s, R66s, H28K, etc.) with iStoreOS firmware (version 20221123 and above). Other firmwares require MPP and RGA to be turned on, and are not guaranteed to be available."
msgstr "RK35xx 系列例如R6SR5SR68sR66sH28K等并使用 iStoreOS 固件版本20221123及以上。其他固件需开启MPP和RGA不保证可用。"
@ -22,6 +22,12 @@ msgstr "x86 系列"
msgid "Raspberry Pi series"
msgstr "树莓派系列"
msgid "Image"
msgstr "镜像"
msgid "Default"
msgstr "默认"
msgid "Media path"
msgstr "媒体路径"

View File

@ -2,9 +2,9 @@
image_name=`uci get jellyfin.@jellyfin[0].image 2>/dev/null`
if [ "$image_name" == "jjm2473/jellyfin-rtk:latest" ]; then
if [ "$image_name" == "jjm2473/jellyfin-rtk:latest" -o "$image_name" == "default" ]; then
uci -q batch <<-EOF >/dev/null
set jellyfin.@jellyfin[0].image="default"
delete jellyfin.@jellyfin[0].image
commit jellyfin
EOF
fi

View File

@ -81,7 +81,7 @@ do_install_detail() {
cmd="$cmd\
-t \
--privileged "
for dev in iep rga dri dma_heap mpp_service mpp-service vpu_service vpu-service \
for dev in iep rga dri dma_heap mali0 mpp_service mpp-service vpu_service vpu-service \
hevc_service hevc-service rkvdec rkvenc avsd vepu h265e ; do
[ -e "/dev/$dev" ] && cmd="$cmd --device /dev/$dev"
done
@ -139,10 +139,10 @@ case ${ACTION} in
docker ${ACTION} jellyfin
;;
"status")
docker ps --all -f 'name=jellyfin' --format '{{.State}}'
docker ps --all -f 'name=^/jellyfin$' --format '{{.State}}'
;;
"port")
docker ps --all -f 'name=jellyfin' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*->8096/tcp' | sed 's/0.0.0.0:\([0-9]*\)->.*/\1/'
docker ps --all -f 'name=^/jellyfin$' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*->8096/tcp' | sed 's/0.0.0.0:\([0-9]*\)->.*/\1/'
;;
*)
usage

View File

@ -2,7 +2,7 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.2.1-20231208
PKG_VERSION:=1.2.1-20240822
PKG_RELEASE:=
LUCI_TITLE:=LuCI support for kodexplorer

View File

@ -73,10 +73,10 @@ case ${ACTION} in
docker ${ACTION} kodexplorer
;;
"status")
docker ps --all -f 'name=kodexplorer' --format '{{.State}}'
docker ps --all -f 'name=^/kodexplorer$' --format '{{.State}}'
;;
"port")
docker ps --all -f 'name=kodexplorer' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*' | sed 's/0.0.0.0://'
docker ps --all -f 'name=^/kodexplorer$' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*' | sed 's/0.0.0.0://'
;;
*)
usage

View File

@ -2,7 +2,7 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.0.1-20231208
PKG_VERSION:=1.0.1-20240822
PKG_RELEASE:=
LUCI_TITLE:=LuCI support for LANraragi

View File

@ -63,10 +63,10 @@ case ${ACTION} in
docker ${ACTION} lanraragi
;;
"status")
docker ps --all -f 'name=lanraragi' --format '{{.State}}'
docker ps --all -f 'name=^/lanraragi$' --format '{{.State}}'
;;
"port")
docker ps --all -f 'name=lanraragi' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*' | sed 's/0.0.0.0://'
docker ps --all -f 'name=^/lanraragi$' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*' | sed 's/0.0.0.0://'
;;
*)
usage

View File

@ -2,7 +2,7 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.0.2-20231208
PKG_VERSION:=1.0.2-20240822
PKG_RELEASE:=
LUCI_TITLE:=LuCI support for Memos

View File

@ -62,10 +62,10 @@ case ${ACTION} in
docker ${ACTION} memos
;;
"status")
docker ps --all -f 'name=memos' --format '{{.State}}'
docker ps --all -f 'name=^/memos$' --format '{{.State}}'
;;
"port")
docker ps --all -f 'name=memos' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*' | sed 's/0.0.0.0://'
docker ps --all -f 'name=^/memos$' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*' | sed 's/0.0.0.0://'
;;
*)
usage

View File

@ -2,7 +2,7 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.0.2-20231208
PKG_VERSION:=1.0.2-20240822
PKG_RELEASE:=
LUCI_TITLE:=LuCI support for MTPhotos

View File

@ -65,10 +65,10 @@ case ${ACTION} in
docker ${ACTION} mtphotos
;;
"status")
docker ps --all -f 'name=mtphotos' --format '{{.State}}'
docker ps --all -f 'name=^/mtphotos$' --format '{{.State}}'
;;
"port")
docker ps --all -f 'name=mtphotos' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*->8063/tcp' | sed 's/0.0.0.0:\([0-9]*\)->.*/\1/'
docker ps --all -f 'name=^/mtphotos$' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*->8063/tcp' | sed 's/0.0.0.0:\([0-9]*\)->.*/\1/'
;;
*)
usage

View File

@ -2,7 +2,7 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.1.3-20231208
PKG_VERSION:=1.1.3-20240822
PKG_RELEASE:=
LUCI_TITLE:=LuCI support for nastools

View File

@ -77,10 +77,10 @@ case ${ACTION} in
docker ${ACTION} nastools
;;
"status")
docker ps --all -f 'name=nastools' --format '{{.State}}'
docker ps --all -f 'name=^/nastools$' --format '{{.State}}'
;;
"port")
docker ps --all -f 'name=nastools' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*' | sed 's/0.0.0.0://'
docker ps --all -f 'name=^/nastools$' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*' | sed 's/0.0.0.0://'
;;
*)
usage

View File

@ -2,7 +2,7 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.0.1-20231208
PKG_VERSION:=1.0.1-20240822
PKG_RELEASE:=
LUCI_TITLE:=LuCI support for Navidrome

View File

@ -63,10 +63,10 @@ case ${ACTION} in
docker ${ACTION} navidrome
;;
"status")
docker ps --all -f 'name=navidrome' --format '{{.State}}'
docker ps --all -f 'name=^/navidrome$' --format '{{.State}}'
;;
"port")
docker ps --all -f 'name=navidrome' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*' | sed 's/0.0.0.0://'
docker ps --all -f 'name=^/navidrome$' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*' | sed 's/0.0.0.0://'
;;
*)
usage

View File

@ -2,7 +2,7 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.1.1-20231208
PKG_VERSION:=1.1.1-20240822
PKG_RELEASE:=
LUCI_TITLE:=LuCI support for nextcloud

View File

@ -72,10 +72,10 @@ case ${ACTION} in
docker ${ACTION} nextcloud
;;
"status")
docker ps --all -f 'name=nextcloud' --format '{{.State}}'
docker ps --all -f 'name=^/nextcloud$' --format '{{.State}}'
;;
"port")
docker ps --all -f 'name=nextcloud' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*' | sed 's/0.0.0.0://'
docker ps --all -f 'name=^/nextcloud$' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*' | sed 's/0.0.0.0://'
;;
*)
usage

View File

@ -2,7 +2,7 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.0.2-20231208
PKG_VERSION:=1.0.2-20240822
PKG_RELEASE:=
LUCI_TITLE:=LuCI support for Owntone

View File

@ -60,7 +60,7 @@ case ${ACTION} in
docker ${ACTION} owntone
;;
"status")
docker ps --all -f 'name=owntone' --format '{{.State}}'
docker ps --all -f 'name=^/owntone$' --format '{{.State}}'
;;
"port")
echo 3689

View File

@ -2,7 +2,7 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.0.0-20221122
PKG_VERSION:=1.0.0-20240822
PKG_RELEASE:=
LUCI_TITLE:=LuCI support for Penpot

View File

@ -60,7 +60,7 @@ case ${ACTION} in
cd $config && docker-compose ${ACTION}
;;
"status")
docker ps --all -f 'name=penpot_penpot-frontend_1' --format '{{.State}}'
docker ps --all -f 'name=^/penpot_penpot-frontend_1$' --format '{{.State}}'
;;
"port")
uci get -q penpot.@main[0].http_port 2>/dev/null

View File

@ -2,7 +2,7 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.0.3-20231208
PKG_VERSION:=1.0.3-20240822
PKG_RELEASE:=
LUCI_TITLE:=LuCI support for PhotoPrism

View File

@ -64,10 +64,10 @@ case ${ACTION} in
docker ${ACTION} photoprism
;;
"status")
docker ps --all -f 'name=photoprism' --format '{{.State}}'
docker ps --all -f 'name=^/photoprism$' --format '{{.State}}'
;;
"port")
docker ps --all -f 'name=photoprism' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*->2342/tcp' | sed 's/0.0.0.0:\([0-9]*\)->.*/\1/'
docker ps --all -f 'name=^/photoprism$' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*->2342/tcp' | sed 's/0.0.0.0:\([0-9]*\)->.*/\1/'
;;
*)
usage

View File

@ -2,7 +2,7 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.0.2-20231208
PKG_VERSION:=1.0.2-20240822
PKG_RELEASE:=
LUCI_TITLE:=LuCI support for Plex

View File

@ -95,10 +95,10 @@ case ${ACTION} in
docker ${ACTION} plex
;;
"status")
docker ps --all -f 'name=plex' --format '{{.State}}'
docker ps --all -f 'name=^/plex$' --format '{{.State}}'
;;
"port")
docker ps --all -f 'name=plex' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*->32400/tcp' | sed 's/0.0.0.0:\([0-9]*\)->.*/\1/'
docker ps --all -f 'name=^/plex$' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*->32400/tcp' | sed 's/0.0.0.0:\([0-9]*\)->.*/\1/'
;;
*)
usage

View File

@ -0,0 +1,24 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=8.3.2-20250106
PKG_RELEASE:=
LUCI_TITLE:=LuCI support for pve
LUCI_PKGARCH:=all
LUCI_DEPENDS:=+lsblk +docker +luci-lib-taskd +vmease
define Package/luci-app-pve/conffiles
/etc/config/pve
endef
define Package/luci-app-pve/prerm
#!/bin/sh
/usr/libexec/istorec/pve.sh stop
exit 0
endef
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature

View File

@ -0,0 +1,8 @@
module("luci.controller.pve", package.seeall)
function index()
entry({"admin", "services", "pve"}, alias("admin", "services", "pve", "config"), _("PVE"), 30).dependent = true
entry({"admin", "services", "pve", "config"}, cbi("pve/config"), _("Config"), 10).leaf = true
entry({"admin", "services", "pve", "tool"}, form("pve/tool"), _("Tool"), 30).leaf = true
end

View File

@ -0,0 +1,53 @@
--[[
LuCI - Lua Configuration Interface
]]--
local taskd = require "luci.model.tasks"
local pve_model = require "luci.model.pve"
local m, s, o
m = taskd.docker_map("pve", "pve", "/usr/libexec/istorec/pve.sh",
translate("Proxmox"),
translate("Proxmox in iStoreOS.") .. " login: root/password. "
.. translate("Official website:") .. ' <a href=\"https://pve.proxmox.com/\" target=\"_blank\">https://pve.proxmox.com/</a>')
s = m:section(SimpleSection, translate("Service Status"), translate("PVE status:"))
s:append(Template("pve/status"))
s = m:section(TypedSection, "pve", translate("Setup"), translate("The following parameters will only take effect during installation or upgrade:"))
s.addremove=false
s.anonymous=true
o = s:option(Value, "http_port", translate("HTTP Port").."<b>*</b>")
o.default = "8006"
o.datatype = "port"
o = s:option(Value, "image_name", translate("Image").."<b>*</b>")
o.rmempty = false
o.datatype = "string"
o:value("linkease/pve:latest", "linkease/pve:latest")
o:value("linkease/pve:8.3.2", "linkease/pve:8.3.2")
o.default = "linkease/pve:latest"
local blocks = pve_model.blocks()
local home = pve_model.home()
o = s:option(Value, "config_path", translate("Config path").."<b>*</b>")
o.rmempty = false
o.datatype = "string"
local paths, default_path = pve_model.find_paths(blocks, home, "Configs")
for _, val in pairs(paths) do
o:value(val, val)
end
o.default = default_path
o = s:option(Value, "root_pwd", "ROOT_PASSWORD")
o.password = true
o.datatype = "string"
o = s:option(Value, "time_zone", translate("Timezone"))
o.datatype = "string"
o:value("Asia/Shanghai", "Asia/Shanghai")
return m

View File

@ -0,0 +1,41 @@
--[[
LuCI - Lua Configuration Interface
]]--
local http = require 'luci.http'
m=SimpleForm("Tools")
m.submit = false
m.reset = false
s = m:section(SimpleSection)
o = s:option(Value, "action", translate("Action").."<b>*</b>")
o.rmempty = false
o.datatype = "string"
o:value("gpu-passthrough", "gpu-passthrough")
o.default = "gpu-passthrough"
local t=Template("pve/tool")
m:append(t)
local btn_do = s:option(Button, "_do")
btn_do.render = function(self, section, scope)
self.inputstyle = "add"
self.title = " "
self.inputtitle = translate("Execute")
Button.render(self, section, scope)
end
btn_do.write = function(self, section, value)
local action = m:get(section, "action")
if action == "gpu-passthrough" then
local cmd = string.format("/usr/libexec/istorec/pve.sh %s", action)
cmd = "/etc/init.d/tasks task_add pve " .. luci.util.shellquote(cmd) .. " >/dev/null 2>&1"
os.execute(cmd)
t.show_log_taskid = "pve"
end
end
return m

View File

@ -0,0 +1,55 @@
local util = require "luci.util"
local jsonc = require "luci.jsonc"
local pve = {}
pve.blocks = function()
local f = io.popen("lsblk -s -f -b -o NAME,FSSIZE,MOUNTPOINT --json", "r")
local vals = {}
if f then
local ret = f:read("*all")
f:close()
local obj = jsonc.parse(ret)
for _, val in pairs(obj["blockdevices"]) do
local fsize = val["fssize"]
if fsize ~= nil and string.len(fsize) > 10 and val["mountpoint"] then
-- fsize > 1G
vals[#vals+1] = val["mountpoint"]
end
end
end
return vals
end
pve.home = function()
local uci = require "luci.model.uci".cursor()
local home_dirs = {}
home_dirs["main_dir"] = uci:get_first("quickstart", "main", "main_dir", "/root")
home_dirs["Configs"] = uci:get_first("quickstart", "main", "conf_dir", home_dirs["main_dir"].."/Configs")
home_dirs["Public"] = uci:get_first("quickstart", "main", "pub_dir", home_dirs["main_dir"].."/Public")
home_dirs["Downloads"] = uci:get_first("quickstart", "main", "dl_dir", home_dirs["Public"].."/Downloads")
home_dirs["Caches"] = uci:get_first("quickstart", "main", "tmp_dir", home_dirs["main_dir"].."/Caches")
return home_dirs
end
pve.find_paths = function(blocks, home_dirs, path_name)
local default_path = ''
local configs = {}
default_path = home_dirs[path_name] .. "/PVE"
if #blocks == 0 then
table.insert(configs, default_path)
else
for _, val in pairs(blocks) do
table.insert(configs, val .. "/" .. path_name .. "/PVE")
end
local without_conf_dir = "/root/" .. path_name .. "/PVE"
if default_path == without_conf_dir then
default_path = configs[1]
end
end
return configs, default_path
end
return pve

View File

@ -0,0 +1,31 @@
<%
local util = require "luci.util"
local container_status = util.trim(util.exec("/usr/libexec/istorec/pve.sh status"))
local container_install = (string.len(container_status) > 0)
local container_running = container_status == "running"
-%>
<div class="cbi-value">
<label class="cbi-value-title"><%:Status%></label>
<div class="cbi-value-field">
<% if container_running then %>
<button class="cbi-button cbi-button-success" disabled="true"><%:PVE is running%></button>
<% else %>
<button class="cbi-button cbi-button-negative" disabled="true"><%:PVE is not running%></button>
<% end %>
</div>
</div>
<%
if container_running then
local port=util.trim(util.exec("/usr/libexec/istorec/pve.sh port"))
if port == "" then
port="8123"
end
-%>
<div class="cbi-value cbi-value-last">
<label class="cbi-value-title">&nbsp;</label>
<div class="cbi-value-field">
<input type="button" class="btn cbi-button cbi-button-apply" name="start" value="<%:Open the PVE%>" onclick="window.open('http://'+location.hostname+':<%=port%>/', '_blank')">
</div>
</div>
<% end %>

View File

@ -0,0 +1,11 @@
<%+tasks/embed%>
<script>
window.addEventListener("load", function(){
const taskd = window.taskd;
<% if self.show_log_taskid then -%>
taskd.show_log("<%=self.show_log_taskid%>");
<%- end %>
});
</script>

View File

@ -0,0 +1,48 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8"
msgid "Official website:"
msgstr "官方网站:"
msgid "Proxmox"
msgstr "Proxmox虚拟机(PVE)"
msgid "Proxmox in iStoreOS."
msgstr "运行在 iStoreOS 上面的 Proxmox(PVE) 虚拟机平台。"
msgid "Config path"
msgstr "配置文件路径"
msgid "Service Status"
msgstr "服务状态"
msgid "PVE status:"
msgstr "PVE 的状态信息如下:"
msgid "Setup"
msgstr "安装配置"
msgid "The following parameters will only take effect during installation or upgrade:"
msgstr "以下参数只在安装或者升级时才会生效:"
msgid "Status"
msgstr "状态"
msgid "PVE is running"
msgstr "PVE 运行中"
msgid "PVE is not running"
msgstr "PVE 未运行"
msgid "Open the PVE"
msgstr "打开 PVE"
msgid "Tool"
msgstr "操作"
msgid "Execute"
msgstr "执行"
msgid "Timezone"
msgstr "时区"

View File

@ -0,0 +1,4 @@
config pve
option 'config_path' ''
option 'http_port' '8006'
option 'image_name' 'linkease/pve:latest'

View File

@ -0,0 +1,129 @@
#!/bin/sh
ACTION=${1}
shift 1
do_install() {
if echo `uname -m` | grep -Eqi 'x86_64'; then
echo "Support x86_64"
else
echo "Not x86_64, only support x86_64, exit"
sleep 3
exit 1
fi
if [ -e /dev/kvm ]; then
echo "/dev/kvm exists"
else
echo "/dev/kvm does not exist"
sleep 3
exit 2
fi
local config=`uci get pve.@pve[0].config_path 2>/dev/null`
local root_pwd=`uci get pve.@pve[0].root_pwd 2>/dev/null`
local IMAGE_NAME=`uci get pve.@pve[0].image_name 2>/dev/null`
local tz=`uci get pve.@pve[0].time_zone 2>/dev/null`
local port=`uci get pve.@pve[0].http_port 2>/dev/null`
if [ -z "$config" ]; then
echo "config path is empty!"
exit 1
fi
[ -z "$port" ] && port=8006
echo "start vmease"
/etc/init.d/vmease start
sleep 1
echo "docker pull ${IMAGE_NAME}"
docker pull ${IMAGE_NAME}
docker rm -f pve
mkdir -p "$config"
local cmd="docker run --restart=unless-stopped -d \
--privileged \
--tmpfs /tmp \
--tmpfs /run/lock \
--hostname pve \
-e "ISTOREOS=1" \
-v \"/var/run:/host/var/run\" \
-v \"$config/vz:/var/lib/vz\" \
-v \"$config/pve-cluster:/var/lib/pve-cluster\" \
--device /dev/kvm:/dev/kvm \
-p $port:8006 \
--dns=172.17.0.1 \
--dns=223.5.5.5 "
[ -e "/dev/vfio" ] && cmd="$cmd -v \"/dev/vfio:/dev/vfio\""
if [ -z "$tz" ]; then
tz="`uci get system.@system[0].zonename | sed 's/ /_/g'`"
fi
[ -z "$tz" ] || cmd="$cmd -e TZ=\"$tz\""
[ -z "$root_pwd" ] || cmd="$cmd -e root_password=\"$root_pwd\""
cmd="$cmd -v /mnt:/mnt"
mountpoint -q /mnt && cmd="$cmd:rslave"
cmd="$cmd --name pve \"$IMAGE_NAME\""
echo "$cmd"
eval "$cmd"
echo "Waiting"
sleep 8
echo "Done"
}
do_gpu_passthrough() {
echo "TODO"
return 0
}
usage() {
echo "usage: $0 sub-command"
echo "where sub-command is one of:"
echo " install Install the pve"
echo " upgrade Upgrade the pve"
echo " rm/start/stop/restart Remove/Start/Stop/Restart the pve"
echo " status pve status"
echo " port pve port"
}
case ${ACTION} in
"install")
do_install
;;
"upgrade")
do_install
;;
"rm")
docker rm -f pve
;;
"start")
/etc/init.d/vmease start
sleep 1
docker ${ACTION} pve
;;
"stop")
docker ${ACTION} pve
;;
"restart")
/etc/init.d/vmease start
sleep 1
docker ${ACTION} pve
;;
"status")
docker ps --all -f 'name=^/pve$' --format '{{.State}}'
;;
"port")
docker ps --all -f 'name=^/pve$' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*' | sed 's/0.0.0.0://'
;;
"gpu-passthrough")
do_gpu_passthrough
;;
*)
usage
exit 1
;;
esac

Some files were not shown because too many files have changed in this diff Show More