diff --git a/luci-app-virtualdog/Makefile b/luci-app-virtualdog/Makefile new file mode 100644 index 00000000..9f397343 --- /dev/null +++ b/luci-app-virtualdog/Makefile @@ -0,0 +1,28 @@ +# +# Copyright (C) 2008-2014 The LuCI Team +# +# 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 diff --git a/luci-app-virtualdog/luasrc/controller/virtualdog.lua b/luci-app-virtualdog/luasrc/controller/virtualdog.lua new file mode 100644 index 00000000..076cc32f --- /dev/null +++ b/luci-app-virtualdog/luasrc/controller/virtualdog.lua @@ -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 diff --git a/luci-app-virtualdog/luasrc/model/cbi/virtualdog.lua b/luci-app-virtualdog/luasrc/model/cbi/virtualdog.lua new file mode 100644 index 00000000..7106feb9 --- /dev/null +++ b/luci-app-virtualdog/luasrc/model/cbi/virtualdog.lua @@ -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 "
" .. virtualdog_model.kvm_help() .. "
" +end + +return m diff --git a/luci-app-virtualdog/luasrc/model/virtualdog.lua b/luci-app-virtualdog/luasrc/model/virtualdog.lua new file mode 100644 index 00000000..2e4d5a4d --- /dev/null +++ b/luci-app-virtualdog/luasrc/model/virtualdog.lua @@ -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 diff --git a/luci-app-virtualdog/luasrc/view/virtualdog/virtualdog_status.htm b/luci-app-virtualdog/luasrc/view/virtualdog/virtualdog_status.htm new file mode 100644 index 00000000..5faf005f --- /dev/null +++ b/luci-app-virtualdog/luasrc/view/virtualdog/virtualdog_status.htm @@ -0,0 +1,21 @@ + + +
+ <%:Status%> +

+ <%:Collecting data...%> +

+
diff --git a/luci-app-virtualdog/po/zh-cn/virtualdog.po b/luci-app-virtualdog/po/zh-cn/virtualdog.po new file mode 100644 index 00000000..32861157 --- /dev/null +++ b/luci-app-virtualdog/po/zh-cn/virtualdog.po @@ -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 "正在获取数据..." diff --git a/luci-app-virtualdog/po/zh_Hans b/luci-app-virtualdog/po/zh_Hans new file mode 120000 index 00000000..41451e4a --- /dev/null +++ b/luci-app-virtualdog/po/zh_Hans @@ -0,0 +1 @@ +zh-cn \ No newline at end of file diff --git a/virtualdog/Makefile b/virtualdog/Makefile new file mode 100644 index 00000000..2db26458 --- /dev/null +++ b/virtualdog/Makefile @@ -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))) diff --git a/virtualdog/files/virtualdog.config b/virtualdog/files/virtualdog.config new file mode 100644 index 00000000..df90b8be --- /dev/null +++ b/virtualdog/files/virtualdog.config @@ -0,0 +1,5 @@ +config virtualdog + option 'enabled' '0' + option 'data_dir' '' + option 'port' '8080' + option 'access_token' '' diff --git a/virtualdog/files/virtualdog.init b/virtualdog/files/virtualdog.init new file mode 100644 index 00000000..ea4c53e5 --- /dev/null +++ b/virtualdog/files/virtualdog.init @@ -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" +} diff --git a/virtualdog/files/virtualdog.uci-default b/virtualdog/files/virtualdog.uci-default new file mode 100644 index 00000000..b60a9638 --- /dev/null +++ b/virtualdog/files/virtualdog.uci-default @@ -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