🍓 Sync 2026-06-28 08:44:52

This commit is contained in:
github-actions[bot] 2026-06-28 08:44:52 +08:00
parent 137c18b95a
commit 31880da43f
11 changed files with 291 additions and 0 deletions

View File

@ -0,0 +1,28 @@
#
# Copyright (C) 2008-2014 The LuCI Team <luci@lists.subsignal.org>
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=virtualdog
PKG_VERSION:=1.0.0
PKG_RELEASE:=1
LUCI_DEPENDS:=+virtualdog
LUCI_MINIFY_CSS:=0
LUCI_MINIFY_JS:=0
define Package/luci-app-virtualdog/conffiles
/etc/config/virtualdog
endef
define Package/luci-app-virtualdog/postrm
#!/bin/sh
rm -f /tmp/luci-indexcache
exit 0
endef
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature

View File

@ -0,0 +1,26 @@
local http = require "luci.http"
module("luci.controller.virtualdog", package.seeall)
function index()
if not nixio.fs.access("/etc/config/virtualdog") then
return
end
local page
page = entry({"admin", "services", "virtualdog"}, cbi("virtualdog"), _("VirtualDog"), 70)
page.dependent = true
entry({"admin", "services", "virtualdog_status"}, call("virtualdog_status"))
end
function virtualdog_status()
local sys = require "luci.sys"
local uci = require "luci.model.uci".cursor()
local port = uci:get_first("virtualdog", "virtualdog", "port") or "8080"
local status = {
running = (sys.call("pidof virtualdogd >/dev/null") == 0),
port = port
}
http.prepare_content("application/json")
http.write_json(status)
end

View File

@ -0,0 +1,34 @@
local m, s
m = Map("virtualdog", translate("VirtualDog"), translate("VirtualDog provides a QEMU/KVM VM management UI."))
m:section(SimpleSection).template = "virtualdog/virtualdog_status"
s = m:section(TypedSection, "virtualdog", translate("Global settings"))
s.addremove = false
s.anonymous = true
s:option(Flag, "enabled", translate("Enable")).rmempty = false
local virtualdog_model = require "luci.model.virtualdog"
local data_dir = s:option(Value, "data_dir", translate("Data directory"))
data_dir.rmempty = false
data_dir.description = translate("Required. VirtualDog stores VM metadata, runtime files and disk images under this directory.")
local port = s:option(Value, "port", translate("Listen port"))
port.default = "8080"
port.rmempty = false
port.datatype = "port"
port.description = translate("Port for VirtualDog HTTP server.")
local access_token = s:option(Value, "access_token", translate("Access token"))
access_token.password = true
access_token.optional = true
local help = s:option(DummyValue, "_kvm_help", translate("KVM packages"))
help.rawhtml = true
function help.cfgvalue()
return "<pre>" .. virtualdog_model.kvm_help() .. "</pre>"
end
return m

View File

@ -0,0 +1,7 @@
local virtualdog = {}
virtualdog.kvm_help = function()
return "amd KVM使用 opkg install kmod-kvm-amd\nintel KVM使用 opkg install kmod-kvm-intel"
end
return virtualdog

View File

@ -0,0 +1,21 @@
<script type="text/javascript">//<![CDATA[
XHR.poll(5, '<%=url("admin/services/virtualdog_status")%>', null, function(x, st) {
var el = document.getElementById('virtualdog_status');
if (st && el) {
if (!st.running) {
el.innerHTML = '<br/><em style="color:red"><%:The VirtualDog service is not running.%></em>';
}
if (st.running) {
el.innerHTML = '<br/><em style="color:green"><%:The VirtualDog service is running.%></em>'
+ "<br/><br/><input class=\"btn cbi-button cbi-button-apply\" type=\"button\" value=\" <%:Click to open VirtualDog%> \" onclick=\"window.open('http://" + window.location.hostname + ":" + st.port + "/')\"/>";
}
}
});
//]]></script>
<fieldset class="cbi-section">
<legend><%:Status%></legend>
<p id="virtualdog_status">
<em><%:Collecting data...%></em>
</p>
</fieldset>

View File

@ -0,0 +1,47 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8"
msgid "VirtualDog"
msgstr "VirtualDog"
msgid "VirtualDog provides a QEMU/KVM VM management UI."
msgstr "VirtualDog 提供一个 QEMU/KVM 虚拟机管理界面。"
msgid "Global settings"
msgstr "全局设置"
msgid "Enable"
msgstr "启用"
msgid "Data directory"
msgstr "数据目录"
msgid "Required. VirtualDog stores VM metadata, runtime files and disk images under this directory."
msgstr "必填。VirtualDog 会将虚拟机元数据、运行文件和磁盘镜像保存在此目录下。"
msgid "Listen port"
msgstr "监听端口"
msgid "Port for VirtualDog HTTP server."
msgstr "VirtualDog HTTP 服务端口。"
msgid "Access token"
msgstr "访问令牌"
msgid "KVM packages"
msgstr "KVM 依赖"
msgid "The VirtualDog service is not running."
msgstr "VirtualDog 服务未运行。"
msgid "The VirtualDog service is running."
msgstr "VirtualDog 服务运行中。"
msgid "Click to open VirtualDog"
msgstr "点击打开 VirtualDog"
msgid "Status"
msgstr "状态"
msgid "Collecting data..."
msgstr "正在获取数据..."

View File

@ -0,0 +1 @@
zh-cn

62
virtualdog/Makefile Normal file
View File

@ -0,0 +1,62 @@
#
# Copyright (C) 2026
#
# This is free software, licensed under the GNU General Public License v3.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=virtualdog
PKG_VERSION:=0.0.1
PKG_RELEASE:=1
# Point this at the released binary tarball when you publish builds.
PKG_SOURCE:=$(PKG_NAME)-binary-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://github.com/Carseason/openwrt-packages/releases/download/prebuilt/
PKG_HASH:=skip
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-binary-$(PKG_VERSION)
PKG_BUILD_PARALLEL:=1
PKG_USE_MIPS16:=0
include $(INCLUDE_DIR)/package.mk
PKG_ARCH_virtualdog:=$(ARCH)
ifeq ($(ARCH),x86_64)
VIRTUALDOG_QEMU_PKG:=qemu-x86_64-softmmu
else ifeq ($(ARCH),aarch64)
VIRTUALDOG_QEMU_PKG:=qemu-aarch64-softmmu
endif
define Package/$(PKG_NAME)
SECTION:=net
CATEGORY:=Network
SUBMENU:=Web Servers/Proxies
TITLE:=VirtualDog
DEPENDS:=@(x86_64||aarch64) +$(VIRTUALDOG_QEMU_PKG) +qemu-img +qemu-bridge-helper +kmod-tun
URL:=https://example.invalid/virtualdog
endef
define Package/$(PKG_NAME)/description
VirtualDog provides a web UI and API for managing QEMU/KVM virtual machines on OpenWrt.
endef
define Package/$(PKG_NAME)/conffiles
/etc/config/virtualdog
endef
define Build/Configure
endef
define Build/Compile
endef
define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/usr/sbin $(1)/etc/init.d $(1)/etc/uci-defaults $(1)/etc/config
$(INSTALL_BIN) $(PKG_BUILD_DIR)/virtualdogd.$(PKG_ARCH_virtualdog) $(1)/usr/sbin/virtualdogd
$(INSTALL_BIN) ./files/virtualdog.init $(1)/etc/init.d/virtualdog
$(INSTALL_BIN) ./files/virtualdog.uci-default $(1)/etc/uci-defaults/09-virtualdog
$(INSTALL_CONF) ./files/virtualdog.config $(1)/etc/config/virtualdog
endef
$(eval $(call BuildPackage,$(PKG_NAME)))

View File

@ -0,0 +1,5 @@
config virtualdog
option 'enabled' '0'
option 'data_dir' ''
option 'port' '8080'
option 'access_token' ''

View File

@ -0,0 +1,39 @@
#!/bin/sh /etc/rc.common
START=93
USE_PROCD=1
get_config() {
config_get_bool enabled "$1" enabled 1
config_get data_dir "$1" data_dir ""
config_get port "$1" port "8080"
config_get access_token "$1" access_token ""
}
start_service() {
config_load virtualdog
config_foreach get_config virtualdog
if [ "$enabled" != 1 ]; then
return 1
fi
if [ -z "$data_dir" ]; then
logger -t virtualdog "data_dir is empty; please set option data_dir in /etc/config/virtualdog"
return 1
fi
mkdir -p "$data_dir" || return 1
logger -t virtualdog "Starting VirtualDog Service"
procd_open_instance virtualdog
procd_set_param command /usr/sbin/virtualdogd --port "$port" --data "$data_dir"
if [ -n "$access_token" ]; then
procd_append_param command --access-token "$access_token"
fi
procd_set_param stderr 1
procd_set_param respawn
procd_close_instance
}
service_triggers() {
procd_add_reload_trigger "virtualdog"
}

View File

@ -0,0 +1,21 @@
#!/bin/sh
[ ! -f "/usr/share/ucitrack/luci-app-virtualdog.json" ] && {
cat > /usr/share/ucitrack/luci-app-virtualdog.json << EEOF
{
"config": "virtualdog",
"init": "virtualdog"
}
EEOF
}
uci -q batch <<-EOF >/dev/null
delete ucitrack.@virtualdog[-1]
add ucitrack virtualdog
set ucitrack.@virtualdog[-1].init=virtualdog
commit ucitrack
EOF
/etc/init.d/virtualdog enable
/etc/init.d/virtualdog start
exit 0