From 30dc36b95d6e0dbc5ab4a332facfc2bd57b6d699 Mon Sep 17 00:00:00 2001 From: ssongliu Date: Tue, 8 Sep 2026 14:20:26 +0800 Subject: [PATCH] feat: integrate virtual machine migration into XPack (#13740) * feat: integrate virtual machine migration into XPack * chore: remove virtual machine test files --- agent/cmd/server/docs/x-log.json | 44 ++++++++++++++-------------- core/cmd/server/docs/x-log.json | 44 ++++++++++++++-------------- core/constant/common.go | 13 ++++---- core/i18n/lang/en.yaml | 1 + core/i18n/lang/es-ES.yaml | 1 + core/i18n/lang/fa.yaml | 1 + core/i18n/lang/ja.yaml | 1 + core/i18n/lang/ko.yaml | 1 + core/i18n/lang/lo.yaml | 1 + core/i18n/lang/ms.yaml | 1 + core/i18n/lang/pt-BR.yaml | 1 + core/i18n/lang/ru.yaml | 1 + core/i18n/lang/tr.yaml | 1 + core/i18n/lang/zh-Hant.yaml | 1 + core/i18n/lang/zh.yaml | 1 + core/init/migration/helper/menu.go | 10 +------ core/init/migration/migrate.go | 1 + core/init/migration/migrations/vm.go | 34 +++++++++++++++++++++ core/middleware/demo_handle.go | 10 +++---- core/middleware/operation.go | 3 +- frontend/src/lang/modules/en.ts | 2 ++ frontend/src/lang/modules/es-es.ts | 2 ++ frontend/src/lang/modules/fa.ts | 2 ++ frontend/src/lang/modules/ja.ts | 2 ++ frontend/src/lang/modules/ko.ts | 2 ++ frontend/src/lang/modules/lo.ts | 2 ++ frontend/src/lang/modules/ms.ts | 2 ++ frontend/src/lang/modules/pt-br.ts | 2 ++ frontend/src/lang/modules/ru.ts | 2 ++ frontend/src/lang/modules/tr.ts | 2 ++ frontend/src/lang/modules/zh-Hant.ts | 1 + frontend/src/lang/modules/zh.ts | 1 + 32 files changed, 127 insertions(+), 66 deletions(-) create mode 100644 core/init/migration/migrations/vm.go diff --git a/agent/cmd/server/docs/x-log.json b/agent/cmd/server/docs/x-log.json index b3ac1bc15..7d46d5134 100644 --- a/agent/cmd/server/docs/x-log.json +++ b/agent/cmd/server/docs/x-log.json @@ -1745,7 +1745,7 @@ "formatZH": "更新 [name]", "formatEN": "update user [name]" }, - "/core/enterprise/vms": { + "/core/xpack/vms": { "bodyKeys": [ "name" ], @@ -1754,7 +1754,7 @@ "formatZH": "创建虚拟机 [name]", "formatEN": "create VM [name]" }, - "/core/enterprise/vms/del": { + "/core/xpack/vms/del": { "bodyKeys": [ "name" ], @@ -1763,14 +1763,14 @@ "formatZH": "删除虚拟机 [name]", "formatEN": "delete VM [name]" }, - "/core/enterprise/vms/environment/enable": { + "/core/xpack/vms/environment/enable": { "bodyKeys": [], "paramKeys": [], "beforeFunctions": [], "formatZH": "启用虚拟机运行环境", "formatEN": "enable VM runtime environment" }, - "/core/enterprise/vms/iso": { + "/core/xpack/vms/iso": { "bodyKeys": [ "name", "type" @@ -1780,7 +1780,7 @@ "formatZH": "创建虚拟机镜像 [name] [type]", "formatEN": "create VM ISO [name] [type]" }, - "/core/enterprise/vms/iso/del": { + "/core/xpack/vms/iso/del": { "bodyKeys": [ "id" ], @@ -1798,7 +1798,7 @@ "formatZH": "删除虚拟机镜像 [name]", "formatEN": "delete VM ISO [name]" }, - "/core/enterprise/vms/iso/update": { + "/core/xpack/vms/iso/update": { "bodyKeys": [ "name", "type" @@ -1808,7 +1808,7 @@ "formatZH": "更新虚拟机镜像 [name] [type]", "formatEN": "update VM ISO [name] [type]" }, - "/core/enterprise/vms/networks": { + "/core/xpack/vms/networks": { "bodyKeys": [ "name", "type" @@ -1818,7 +1818,7 @@ "formatZH": "创建虚拟机网络 [name] [type]", "formatEN": "create VM network [name] [type]" }, - "/core/enterprise/vms/networks/del": { + "/core/xpack/vms/networks/del": { "bodyKeys": [ "id" ], @@ -1836,7 +1836,7 @@ "formatZH": "删除虚拟机网络 [name]", "formatEN": "delete VM network [name]" }, - "/core/enterprise/vms/networks/update": { + "/core/xpack/vms/networks/update": { "bodyKeys": [ "id" ], @@ -1854,7 +1854,7 @@ "formatZH": "更新虚拟机网络 [name]", "formatEN": "update VM network [name]" }, - "/core/enterprise/vms/operate": { + "/core/xpack/vms/operate": { "bodyKeys": [ "name", "operate" @@ -1864,14 +1864,14 @@ "formatZH": "操作虚拟机 [name] [operate]", "formatEN": "operate VM [name] [operate]" }, - "/core/enterprise/vms/orphans/clean": { + "/core/xpack/vms/orphans/clean": { "bodyKeys": [], "paramKeys": [], "beforeFunctions": [], "formatZH": "清理虚拟机孤立数据", "formatEN": "clean VM orphaned data" }, - "/core/enterprise/vms/rename": { + "/core/xpack/vms/rename": { "bodyKeys": [ "name", "newName" @@ -1881,7 +1881,7 @@ "formatZH": "重命名虚拟机 [name] 为 [newName]", "formatEN": "rename VM [name] to [newName]" }, - "/core/enterprise/vms/snapshots": { + "/core/xpack/vms/snapshots": { "bodyKeys": [ "name", "snapshotName" @@ -1891,7 +1891,7 @@ "formatZH": "创建虚拟机 [name] 快照 [snapshotName]", "formatEN": "create VM [name] snapshot [snapshotName]" }, - "/core/enterprise/vms/snapshots/del": { + "/core/xpack/vms/snapshots/del": { "bodyKeys": [ "name", "snapshotName" @@ -1901,7 +1901,7 @@ "formatZH": "删除虚拟机 [name] 快照 [snapshotName]", "formatEN": "delete VM [name] snapshot [snapshotName]" }, - "/core/enterprise/vms/snapshots/recover": { + "/core/xpack/vms/snapshots/recover": { "bodyKeys": [ "name", "snapshotName" @@ -1911,7 +1911,7 @@ "formatZH": "恢复虚拟机 [name] 快照 [snapshotName]", "formatEN": "recover VM [name] snapshot [snapshotName]" }, - "/core/enterprise/vms/storages": { + "/core/xpack/vms/storages": { "bodyKeys": [ "name", "type" @@ -1921,7 +1921,7 @@ "formatZH": "创建虚拟机存储 [name] [type]", "formatEN": "create VM storage [name] [type]" }, - "/core/enterprise/vms/storages/del": { + "/core/xpack/vms/storages/del": { "bodyKeys": [ "id" ], @@ -1939,7 +1939,7 @@ "formatZH": "删除虚拟机存储 [name]", "formatEN": "delete VM storage [name]" }, - "/core/enterprise/vms/storages/update": { + "/core/xpack/vms/storages/update": { "bodyKeys": [ "id" ], @@ -1957,14 +1957,14 @@ "formatZH": "更新虚拟机存储 [name]", "formatEN": "update VM storage [name]" }, - "/core/enterprise/vms/sync": { + "/core/xpack/vms/sync": { "bodyKeys": [], "paramKeys": [], "beforeFunctions": [], "formatZH": "同步虚拟机", "formatEN": "sync virtual machines" }, - "/core/enterprise/vms/templates": { + "/core/xpack/vms/templates": { "bodyKeys": [ "name", "templateName" @@ -1974,7 +1974,7 @@ "formatZH": "创建虚拟机 [name] 模板 [templateName]", "formatEN": "create VM [name] template [templateName]" }, - "/core/enterprise/vms/templates/del": { + "/core/xpack/vms/templates/del": { "bodyKeys": [ "id" ], @@ -1992,7 +1992,7 @@ "formatZH": "删除虚拟机模板 [name]", "formatEN": "delete VM template [name]" }, - "/core/enterprise/vms/update": { + "/core/xpack/vms/update": { "bodyKeys": [ "name" ], diff --git a/core/cmd/server/docs/x-log.json b/core/cmd/server/docs/x-log.json index b3ac1bc15..7d46d5134 100644 --- a/core/cmd/server/docs/x-log.json +++ b/core/cmd/server/docs/x-log.json @@ -1745,7 +1745,7 @@ "formatZH": "更新 [name]", "formatEN": "update user [name]" }, - "/core/enterprise/vms": { + "/core/xpack/vms": { "bodyKeys": [ "name" ], @@ -1754,7 +1754,7 @@ "formatZH": "创建虚拟机 [name]", "formatEN": "create VM [name]" }, - "/core/enterprise/vms/del": { + "/core/xpack/vms/del": { "bodyKeys": [ "name" ], @@ -1763,14 +1763,14 @@ "formatZH": "删除虚拟机 [name]", "formatEN": "delete VM [name]" }, - "/core/enterprise/vms/environment/enable": { + "/core/xpack/vms/environment/enable": { "bodyKeys": [], "paramKeys": [], "beforeFunctions": [], "formatZH": "启用虚拟机运行环境", "formatEN": "enable VM runtime environment" }, - "/core/enterprise/vms/iso": { + "/core/xpack/vms/iso": { "bodyKeys": [ "name", "type" @@ -1780,7 +1780,7 @@ "formatZH": "创建虚拟机镜像 [name] [type]", "formatEN": "create VM ISO [name] [type]" }, - "/core/enterprise/vms/iso/del": { + "/core/xpack/vms/iso/del": { "bodyKeys": [ "id" ], @@ -1798,7 +1798,7 @@ "formatZH": "删除虚拟机镜像 [name]", "formatEN": "delete VM ISO [name]" }, - "/core/enterprise/vms/iso/update": { + "/core/xpack/vms/iso/update": { "bodyKeys": [ "name", "type" @@ -1808,7 +1808,7 @@ "formatZH": "更新虚拟机镜像 [name] [type]", "formatEN": "update VM ISO [name] [type]" }, - "/core/enterprise/vms/networks": { + "/core/xpack/vms/networks": { "bodyKeys": [ "name", "type" @@ -1818,7 +1818,7 @@ "formatZH": "创建虚拟机网络 [name] [type]", "formatEN": "create VM network [name] [type]" }, - "/core/enterprise/vms/networks/del": { + "/core/xpack/vms/networks/del": { "bodyKeys": [ "id" ], @@ -1836,7 +1836,7 @@ "formatZH": "删除虚拟机网络 [name]", "formatEN": "delete VM network [name]" }, - "/core/enterprise/vms/networks/update": { + "/core/xpack/vms/networks/update": { "bodyKeys": [ "id" ], @@ -1854,7 +1854,7 @@ "formatZH": "更新虚拟机网络 [name]", "formatEN": "update VM network [name]" }, - "/core/enterprise/vms/operate": { + "/core/xpack/vms/operate": { "bodyKeys": [ "name", "operate" @@ -1864,14 +1864,14 @@ "formatZH": "操作虚拟机 [name] [operate]", "formatEN": "operate VM [name] [operate]" }, - "/core/enterprise/vms/orphans/clean": { + "/core/xpack/vms/orphans/clean": { "bodyKeys": [], "paramKeys": [], "beforeFunctions": [], "formatZH": "清理虚拟机孤立数据", "formatEN": "clean VM orphaned data" }, - "/core/enterprise/vms/rename": { + "/core/xpack/vms/rename": { "bodyKeys": [ "name", "newName" @@ -1881,7 +1881,7 @@ "formatZH": "重命名虚拟机 [name] 为 [newName]", "formatEN": "rename VM [name] to [newName]" }, - "/core/enterprise/vms/snapshots": { + "/core/xpack/vms/snapshots": { "bodyKeys": [ "name", "snapshotName" @@ -1891,7 +1891,7 @@ "formatZH": "创建虚拟机 [name] 快照 [snapshotName]", "formatEN": "create VM [name] snapshot [snapshotName]" }, - "/core/enterprise/vms/snapshots/del": { + "/core/xpack/vms/snapshots/del": { "bodyKeys": [ "name", "snapshotName" @@ -1901,7 +1901,7 @@ "formatZH": "删除虚拟机 [name] 快照 [snapshotName]", "formatEN": "delete VM [name] snapshot [snapshotName]" }, - "/core/enterprise/vms/snapshots/recover": { + "/core/xpack/vms/snapshots/recover": { "bodyKeys": [ "name", "snapshotName" @@ -1911,7 +1911,7 @@ "formatZH": "恢复虚拟机 [name] 快照 [snapshotName]", "formatEN": "recover VM [name] snapshot [snapshotName]" }, - "/core/enterprise/vms/storages": { + "/core/xpack/vms/storages": { "bodyKeys": [ "name", "type" @@ -1921,7 +1921,7 @@ "formatZH": "创建虚拟机存储 [name] [type]", "formatEN": "create VM storage [name] [type]" }, - "/core/enterprise/vms/storages/del": { + "/core/xpack/vms/storages/del": { "bodyKeys": [ "id" ], @@ -1939,7 +1939,7 @@ "formatZH": "删除虚拟机存储 [name]", "formatEN": "delete VM storage [name]" }, - "/core/enterprise/vms/storages/update": { + "/core/xpack/vms/storages/update": { "bodyKeys": [ "id" ], @@ -1957,14 +1957,14 @@ "formatZH": "更新虚拟机存储 [name]", "formatEN": "update VM storage [name]" }, - "/core/enterprise/vms/sync": { + "/core/xpack/vms/sync": { "bodyKeys": [], "paramKeys": [], "beforeFunctions": [], "formatZH": "同步虚拟机", "formatEN": "sync virtual machines" }, - "/core/enterprise/vms/templates": { + "/core/xpack/vms/templates": { "bodyKeys": [ "name", "templateName" @@ -1974,7 +1974,7 @@ "formatZH": "创建虚拟机 [name] 模板 [templateName]", "formatEN": "create VM [name] template [templateName]" }, - "/core/enterprise/vms/templates/del": { + "/core/xpack/vms/templates/del": { "bodyKeys": [ "id" ], @@ -1992,7 +1992,7 @@ "formatZH": "删除虚拟机模板 [name]", "formatEN": "delete VM template [name]" }, - "/core/enterprise/vms/update": { + "/core/xpack/vms/update": { "bodyKeys": [ "name" ], diff --git a/core/constant/common.go b/core/constant/common.go index 0822fcb9f..6ba43945a 100644 --- a/core/constant/common.go +++ b/core/constant/common.go @@ -224,12 +224,13 @@ var WebUrlMap = map[string]struct{}{ "/enterprise/ops-report/alert": {}, "/enterprise/ops-report/history": {}, "/enterprise/ops-report/settings": {}, - "/enterprise/vm/overview": {}, - "/enterprise/vm/list": {}, - "/enterprise/vm/isos": {}, - "/enterprise/vm/templates": {}, - "/enterprise/vm/networks": {}, - "/enterprise/vm/storage-pools": {}, + "/xpack/vm": {}, + "/xpack/vm/overview": {}, + "/xpack/vm/list": {}, + "/xpack/vm/isos": {}, + "/xpack/vm/templates": {}, + "/xpack/vm/networks": {}, + "/xpack/vm/storage-pools": {}, } var DynamicRoutes = []string{ diff --git a/core/i18n/lang/en.yaml b/core/i18n/lang/en.yaml index 4aa6a6a42..d1010fc80 100644 --- a/core/i18n/lang/en.yaml +++ b/core/i18n/lang/en.yaml @@ -135,6 +135,7 @@ ClusterMasterNotExist: "Cluster master node is disconnected. Delete child nodes. # virtual machine ErrVMNotFound: "Virtual machine does not exist" ErrVMAlreadyExists: "Virtual machine already exists" +ErrVMCountLimit: "The Professional edition supports up to {{ .limit }} virtual machines. Delete an existing VM or upgrade to Enterprise to create more." ErrVMImageAlreadyExists: "Virtual machine image already exists: {{ .detail }}" ErrVMStoragePathInUse: "Storage pool path is already used by [{{ .name }}]" ErrVMHelperNotFound: "1panel-kvm not found" diff --git a/core/i18n/lang/es-ES.yaml b/core/i18n/lang/es-ES.yaml index e3b02f563..362582066 100644 --- a/core/i18n/lang/es-ES.yaml +++ b/core/i18n/lang/es-ES.yaml @@ -135,6 +135,7 @@ ClusterMasterNotExist: "El nodo principal del clúster está desconectado, elimi # máquina virtual ErrVMNotFound: "La máquina virtual no existe" ErrVMAlreadyExists: "La máquina virtual ya existe" +ErrVMCountLimit: "La edición Professional permite crear hasta {{ .limit }} máquinas virtuales. Elimina una máquina virtual existente o actualiza a Enterprise y vuelve a intentarlo." ErrVMImageAlreadyExists: "La imagen de la máquina virtual ya existe: {{ .detail }}" ErrVMStoragePathInUse: "La ruta del pool de almacenamiento ya está usada por [{{ .name }}]" ErrVMHelperNotFound: "No se encontró 1panel-kvm" diff --git a/core/i18n/lang/fa.yaml b/core/i18n/lang/fa.yaml index e4ea9a9bc..978f0d6c4 100644 --- a/core/i18n/lang/fa.yaml +++ b/core/i18n/lang/fa.yaml @@ -135,6 +135,7 @@ ClusterMasterNotExist: "گره اصلی خوشه قطع شده است. گره‌ # ماشین مجازی ErrVMNotFound: "ماشین مجازی وجود ندارد" ErrVMAlreadyExists: "ماشین مجازی از قبل وجود دارد" +ErrVMCountLimit: "در نسخه Professional می‌توانید حداکثر {{ .limit }} ماشین مجازی ایجاد کنید. یک ماشین مجازی موجود را حذف کنید یا به نسخه Enterprise ارتقا دهید و دوباره تلاش کنید." ErrVMImageAlreadyExists: "فایل ایمیج ماشین مجازی از قبل وجود دارد: {{ .detail }}" ErrVMStoragePathInUse: "مسیر استخر ذخیره‌سازی قبلاً توسط [{{ .name }}] استفاده شده است" ErrVMHelperNotFound: "1panel-kvm یافت نشد" diff --git a/core/i18n/lang/ja.yaml b/core/i18n/lang/ja.yaml index 17bac16ac..b059f47e1 100644 --- a/core/i18n/lang/ja.yaml +++ b/core/i18n/lang/ja.yaml @@ -135,6 +135,7 @@ ClusterMasterNotExist: "クラスタのマスターノードが切断されて # 仮想マシン ErrVMNotFound: "仮想マシンが存在しません" ErrVMAlreadyExists: "仮想マシンは既に存在します" +ErrVMCountLimit: "Professional 版では最大 {{ .limit }} 台の仮想マシンを作成できます。既存の仮想マシンを削除するか、Enterprise 版にアップグレードしてから再試行してください。" ErrVMImageAlreadyExists: "仮想マシンのイメージファイルは既に存在します: {{ .detail }}" ErrVMStoragePathInUse: "ストレージプールのパスは既に [{{ .name }}] で使用されています" ErrVMHelperNotFound: "1panel-kvm が見つかりません" diff --git a/core/i18n/lang/ko.yaml b/core/i18n/lang/ko.yaml index 4606b8d59..ac73a9811 100644 --- a/core/i18n/lang/ko.yaml +++ b/core/i18n/lang/ko.yaml @@ -135,6 +135,7 @@ ClusterMasterNotExist: "클러스터의 마스터 노드가 연결이 끊어졌 # 가상 머신 ErrVMNotFound: "가상 머신이 존재하지 않습니다" ErrVMAlreadyExists: "가상 머신이 이미 존재합니다" +ErrVMCountLimit: "Professional 버전에서는 가상 머신을 최대 {{ .limit }}대까지 생성할 수 있습니다. 기존 가상 머신을 삭제하거나 Enterprise 버전으로 업그레이드한 후 다시 시도하세요." ErrVMImageAlreadyExists: "가상 머신 이미지 파일이 이미 존재합니다: {{ .detail }}" ErrVMStoragePathInUse: "스토리지 풀 경로가 이미 [{{ .name }}]에서 사용 중입니다" ErrVMHelperNotFound: "1panel-kvm을 찾을 수 없습니다" diff --git a/core/i18n/lang/lo.yaml b/core/i18n/lang/lo.yaml index cf9060676..b6120b12a 100644 --- a/core/i18n/lang/lo.yaml +++ b/core/i18n/lang/lo.yaml @@ -135,6 +135,7 @@ ClusterMasterNotExist: "ໂນດຫຼັກຂອງຄລັສເຕີຖ # virtual machine ErrVMNotFound: "ບໍ່ມີເຄື່ອງສະເໝືອນ" ErrVMAlreadyExists: "ມີເຄື່ອງສະເໝືອນຢູ່ແລ້ວ" +ErrVMCountLimit: "ລຸ້ນ Professional ສາມາດສ້າງເຄື່ອງສະເໝືອນໄດ້ສູງສຸດ {{ .limit }} ເຄື່ອງ. ກະລຸນາລຶບເຄື່ອງສະເໝືອນທີ່ມີຢູ່ ຫຼື ອັບເກຣດເປັນລຸ້ນ Enterprise ແລ້ວລອງອີກຄັ້ງ." ErrVMImageAlreadyExists: "ມີອິມເມຈເຄື່ອງສະເໝືອນຢູ່ແລ້ວ: {{ .detail }}" ErrVMStoragePathInUse: "ເສັ້ນທາງພູນຈັດເກັບຖືກໃຊ້ໂດຍ [{{ .name }}] ແລ້ວ" ErrVMHelperNotFound: "ບໍ່ພົບ 1panel-kvm" diff --git a/core/i18n/lang/ms.yaml b/core/i18n/lang/ms.yaml index 008f43cf9..21f92c7f7 100644 --- a/core/i18n/lang/ms.yaml +++ b/core/i18n/lang/ms.yaml @@ -135,6 +135,7 @@ ClusterMasterNotExist: "Node utama kluster terputus, sila padamkan nod anak." # mesin maya ErrVMNotFound: "Mesin maya tidak wujud" ErrVMAlreadyExists: "Mesin maya sudah wujud" +ErrVMCountLimit: "Edisi Professional membenarkan penciptaan sehingga {{ .limit }} mesin maya. Padamkan mesin maya sedia ada atau naik taraf kepada Enterprise dan cuba lagi." ErrVMImageAlreadyExists: "Fail imej mesin maya sudah wujud: {{ .detail }}" ErrVMStoragePathInUse: "Laluan kolam storan sudah digunakan oleh [{{ .name }}]" ErrVMHelperNotFound: "1panel-kvm tidak ditemui" diff --git a/core/i18n/lang/pt-BR.yaml b/core/i18n/lang/pt-BR.yaml index d1e9dfd51..0c727822a 100644 --- a/core/i18n/lang/pt-BR.yaml +++ b/core/i18n/lang/pt-BR.yaml @@ -135,6 +135,7 @@ ClusterMasterNotExist: "O nó mestre do cluster está desconectado, por favor, e # máquina virtual ErrVMNotFound: "Máquina virtual não existe" ErrVMAlreadyExists: "Máquina virtual já existe" +ErrVMCountLimit: "A edição Professional permite criar até {{ .limit }} máquinas virtuais. Exclua uma máquina virtual existente ou atualize para Enterprise e tente novamente." ErrVMImageAlreadyExists: "A imagem da máquina virtual já existe: {{ .detail }}" ErrVMStoragePathInUse: "O caminho do pool de armazenamento já é usado por [{{ .name }}]" ErrVMHelperNotFound: "1panel-kvm não encontrado" diff --git a/core/i18n/lang/ru.yaml b/core/i18n/lang/ru.yaml index 3cac24627..50fe894a2 100644 --- a/core/i18n/lang/ru.yaml +++ b/core/i18n/lang/ru.yaml @@ -135,6 +135,7 @@ ClusterMasterNotExist: "Основной узел кластера отключ # виртуальная машина ErrVMNotFound: "Виртуальная машина не существует" ErrVMAlreadyExists: "Виртуальная машина уже существует" +ErrVMCountLimit: "В редакции Professional можно создать не более {{ .limit }} виртуальных машин. Удалите существующую виртуальную машину или перейдите на Enterprise и повторите попытку." ErrVMImageAlreadyExists: "Файл образа виртуальной машины уже существует: {{ .detail }}" ErrVMStoragePathInUse: "Путь пула хранения уже используется [{{ .name }}]" ErrVMHelperNotFound: "1panel-kvm не найден" diff --git a/core/i18n/lang/tr.yaml b/core/i18n/lang/tr.yaml index 90afba460..0f4ea12e6 100644 --- a/core/i18n/lang/tr.yaml +++ b/core/i18n/lang/tr.yaml @@ -135,6 +135,7 @@ ClusterMasterNotExist: "Küme ana düğümü bağlantısı kesildi, lütfen alt # sanal makine ErrVMNotFound: "Sanal makine mevcut değil" ErrVMAlreadyExists: "Sanal makine zaten mevcut" +ErrVMCountLimit: "Professional sürümü en fazla {{ .limit }} sanal makine oluşturulmasına izin verir. Mevcut bir sanal makineyi silin veya Enterprise sürümüne yükseltip tekrar deneyin." ErrVMImageAlreadyExists: "Sanal makine imaj dosyası zaten mevcut: {{ .detail }}" ErrVMStoragePathInUse: "Depolama havuzu yolu zaten [{{ .name }}] tarafından kullanılıyor" ErrVMHelperNotFound: "1panel-kvm bulunamadı" diff --git a/core/i18n/lang/zh-Hant.yaml b/core/i18n/lang/zh-Hant.yaml index 33cf1e996..52397dcf9 100644 --- a/core/i18n/lang/zh-Hant.yaml +++ b/core/i18n/lang/zh-Hant.yaml @@ -135,6 +135,7 @@ ClusterMasterNotExist: "叢集主節點失聯,請刪除子節點" # 虛擬機 ErrVMNotFound: "虛擬機不存在" ErrVMAlreadyExists: "虛擬機已存在" +ErrVMCountLimit: "專業版最多可建立 {{ .limit }} 台虛擬機,請刪除現有虛擬機或升級企業版後重試。" ErrVMImageAlreadyExists: "虛擬機映像檔已存在: {{ .detail }}" ErrVMStoragePathInUse: "儲存池路徑已被 [{{ .name }}] 使用" ErrVMHelperNotFound: "1panel-kvm 不存在" diff --git a/core/i18n/lang/zh.yaml b/core/i18n/lang/zh.yaml index c3ffd792b..c5416c4b6 100644 --- a/core/i18n/lang/zh.yaml +++ b/core/i18n/lang/zh.yaml @@ -135,6 +135,7 @@ ClusterMasterNotExist: "集群主节点失联,请删除子节点" # 虚拟机 ErrVMNotFound: "虚拟机不存在" ErrVMAlreadyExists: "虚拟机已存在" +ErrVMCountLimit: "专业版最多可创建 {{ .limit }} 台虚拟机,请删除已有虚拟机或升级企业版后重试。" ErrVMImageAlreadyExists: "虚拟机镜像文件已存在: {{ .detail }}" ErrVMStoragePathInUse: "存储池路径已被 [{{ .name }}] 使用" ErrVMHelperNotFound: "1panel-kvm 不存在" diff --git a/core/init/migration/helper/menu.go b/core/init/migration/helper/menu.go index b73e38c6d..c7598d4b6 100644 --- a/core/init/migration/helper/menu.go +++ b/core/init/migration/helper/menu.go @@ -131,6 +131,7 @@ func LoadMenus() string { {ID: "111", Disabled: false, Title: "xpack.node.nodeManagement", IsShow: true, Label: "NodeDashboard", Path: "/xpack/node/dashboard", Sort: 300}, {ID: "113", Disabled: false, Title: "xpack.monitor.name", IsShow: true, Label: "MonitorDashboard", Path: "/xpack/monitor/dashboard", Sort: 600}, {ID: "115", Disabled: false, Title: "xpack.sync.menu", IsShow: true, Label: "Sync", Path: "/xpack/sync", Sort: 700}, + {ID: "123", Disabled: false, Title: "xpack.vm.title", IsShow: true, Label: "VirtualMachine", Path: "/xpack/vm", Sort: 900}, {ID: "114", Disabled: false, Title: "xpack.tamper.tamper", IsShow: true, Label: "Tamper", Path: "/xpack/tamper", Sort: 1000}, {ID: "120", Disabled: false, Title: "xpack.cluster.cluster", IsShow: true, Label: "Cluster", Path: "/xpack/cluster", Sort: 1100}, {ID: "117", Disabled: false, Title: "xpack.setting.setting", IsShow: true, Label: "XSetting", Path: "/xpack/setting", Sort: 1200}, @@ -191,15 +192,6 @@ func LoadMenus() string { Path: "/enterprise/ops-report", Sort: 500, }, "UserManagement") - item[i].Children = UpsertMenuByLabel(item[i].Children, dto.ShowMenu{ - ID: "123", - Disabled: false, - Title: "xpack.vm.title", - IsShow: true, - Label: "VirtualMachine", - Path: "/enterprise/vm", - Sort: 900, - }, "Sync") break } } diff --git a/core/init/migration/migrate.go b/core/init/migration/migrate.go index 5f75d285a..a34a33dba 100644 --- a/core/init/migration/migrate.go +++ b/core/init/migration/migrate.go @@ -66,5 +66,6 @@ func coreMigrations() []*gormigrate.Migration { migrations.RepairXpackAppMenus, migrations.UpdateFirewallMenuPath, migrations.RemoveUpageHideMenu, + migrations.MoveVirtualMachineMenuToXpack, } } diff --git a/core/init/migration/migrations/vm.go b/core/init/migration/migrations/vm.go new file mode 100644 index 000000000..447f1f24e --- /dev/null +++ b/core/init/migration/migrations/vm.go @@ -0,0 +1,34 @@ +package migrations + +import ( + "github.com/1Panel-dev/1Panel/core/app/dto" + "github.com/1Panel-dev/1Panel/core/init/migration/helper" + "github.com/go-gormigrate/gormigrate/v2" + "gorm.io/gorm" +) + +var MoveVirtualMachineMenuToXpack = &gormigrate.Migration{ + ID: "20260908-move-vm-menu-to-xpack", + Migrate: func(tx *gorm.DB) error { + return helper.UpdateHideMenu(tx, func(menus []dto.ShowMenu) []dto.ShowMenu { + for i := range menus { + if menus[i].Label != "Xpack-Menu" { + continue + } + for j := range menus[i].Children { + if menus[i].Children[j].Label == "VirtualMachine" { + // Keep the user's visibility preference and ordering. + menus[i].Children[j].Path = "/xpack/vm" + return menus + } + } + menus[i].Children = helper.UpsertMenuByLabel(menus[i].Children, dto.ShowMenu{ + ID: "123", Title: "xpack.vm.title", IsShow: true, + Label: "VirtualMachine", Path: "/xpack/vm", Sort: 900, + }, "Sync") + break + } + return menus + }) + }, +} diff --git a/core/middleware/demo_handle.go b/core/middleware/demo_handle.go index e418221c8..bbd5fe481 100644 --- a/core/middleware/demo_handle.go +++ b/core/middleware/demo_handle.go @@ -78,11 +78,11 @@ var demoAllowedRoutes = map[demoRoute]struct{}{ } var demoDeniedRoutes = map[demoRoute]struct{}{ - {http.MethodGet, "/api/v2/containers/exec"}: {}, - {http.MethodGet, "/api/v2/hosts/terminal/local"}: {}, - {http.MethodGet, "/api/v2/hosts/terminal/ssh"}: {}, - {http.MethodGet, "/api/v2/hosts/terminal/container"}: {}, - {http.MethodGet, "/api/v2/core/enterprise/vms/console/ws"}: {}, + {http.MethodGet, "/api/v2/containers/exec"}: {}, + {http.MethodGet, "/api/v2/hosts/terminal/local"}: {}, + {http.MethodGet, "/api/v2/hosts/terminal/ssh"}: {}, + {http.MethodGet, "/api/v2/hosts/terminal/container"}: {}, + {http.MethodGet, "/api/v2/core/xpack/vms/console/ws"}: {}, } func DemoHandle() gin.HandlerFunc { diff --git a/core/middleware/operation.go b/core/middleware/operation.go index 47fb6d379..8ad745969 100644 --- a/core/middleware/operation.go +++ b/core/middleware/operation.go @@ -42,8 +42,7 @@ func OperationLog() gin.HandlerFunc { } source := loadLogInfo(c.Request.URL.Path) - pathItem := strings.TrimPrefix(c.Request.URL.Path, "/api/v2") - pathItem = strings.TrimPrefix(pathItem, "/api/v2/core") + pathItem := normalizeOperationPath(c.Request.URL.Path) currentNodeItem := c.Request.Header.Get("CurrentNode") currentNode, _ := url.QueryUnescape(currentNodeItem) record := &model.OperationLog{ diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index 560cfd6ba..c9c438c60 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -6928,6 +6928,8 @@ const message = { }, overview: 'Overview', dependencies: 'Dependencies', + architectureUnsupported: + 'The current system architecture {0} is not supported. VM features currently support AMD64 and ARM64 only.', dependencyPurpose: 'Purpose', dependencyPurposeMap: { libvirt: 'Provides VM management services for lifecycle control and resource scheduling.', diff --git a/frontend/src/lang/modules/es-es.ts b/frontend/src/lang/modules/es-es.ts index 7eb91499e..7af679eb3 100644 --- a/frontend/src/lang/modules/es-es.ts +++ b/frontend/src/lang/modules/es-es.ts @@ -7037,6 +7037,8 @@ const message = { }, }, dependencies: 'Dependencias', + architectureUnsupported: + 'La arquitectura actual del sistema, {0}, no es compatible. Las funciones de VM solo admiten AMD64 y ARM64.', dependencyPurpose: 'Propósito', dependencyPurposeMap: { libvirt: 'Proporciona servicios de gestión de VM para el ciclo de vida y la planificación de recursos.', diff --git a/frontend/src/lang/modules/fa.ts b/frontend/src/lang/modules/fa.ts index 3236f6490..0a199a3e2 100644 --- a/frontend/src/lang/modules/fa.ts +++ b/frontend/src/lang/modules/fa.ts @@ -6881,6 +6881,8 @@ const message = { }, }, dependencies: 'وابستگی‌ها', + architectureUnsupported: + 'معماری فعلی سیستم، {0}، پشتیبانی نمی‌شود. قابلیت ماشین مجازی در حال حاضر فقط از AMD64 و ARM64 پشتیبانی می‌کند.', dependencyPurpose: 'کاربرد', dependencyPurposeMap: { libvirt: 'سرویس مدیریت ماشین مجازی را برای چرخه حیات و زمان‌بندی منابع فراهم می‌کند.', diff --git a/frontend/src/lang/modules/ja.ts b/frontend/src/lang/modules/ja.ts index c607cb230..ccd19bdb7 100644 --- a/frontend/src/lang/modules/ja.ts +++ b/frontend/src/lang/modules/ja.ts @@ -6917,6 +6917,8 @@ const message = { }, }, dependencies: '依存関係', + architectureUnsupported: + '現在のシステムアーキテクチャ {0} はサポートされていません。VM 機能は AMD64 と ARM64 のみをサポートしています。', dependencyPurpose: '用途', dependencyPurposeMap: { libvirt: '仮想マシン管理サービスを提供し、ライフサイクルとリソーススケジューリングを担当します。', diff --git a/frontend/src/lang/modules/ko.ts b/frontend/src/lang/modules/ko.ts index f05a8874e..adbd8a4ad 100644 --- a/frontend/src/lang/modules/ko.ts +++ b/frontend/src/lang/modules/ko.ts @@ -6780,6 +6780,8 @@ const message = { }, }, dependencies: '종속성', + architectureUnsupported: + '현재 시스템 아키텍처 {0}은(는) 지원되지 않습니다. VM 기능은 현재 AMD64 및 ARM64만 지원합니다.', dependencyPurpose: '용도', dependencyPurposeMap: { libvirt: '가상 머신 관리 서비스를 제공하며 수명 주기와 리소스 스케줄링을 담당합니다.', diff --git a/frontend/src/lang/modules/lo.ts b/frontend/src/lang/modules/lo.ts index 5400663ad..b446660fa 100644 --- a/frontend/src/lang/modules/lo.ts +++ b/frontend/src/lang/modules/lo.ts @@ -6696,6 +6696,8 @@ const message = { }, overview: 'ພາບລວມ', dependencies: 'ສິ່ງຂຶ້ນກັບ', + architectureUnsupported: + 'ສະຖາປັດຕະຍະກຳລະບົບ {0} ຍັງບໍ່ຮອງຮັບ. ຟັງຊັນ VM ປັດຈຸບັນຮອງຮັບສະເພາະ AMD64 ແລະ ARM64.', dependencyPurpose: 'ຈຸດປະສົງ', dependencyPurposeMap: { libvirt: 'ໃຫ້ບໍລິການຈັດການ VM ສຳລັບຄວບຄຸມວົງຈອນຊີວິດ ແລະ ຈັດສັນຊັບພະຍາກອນ.', diff --git a/frontend/src/lang/modules/ms.ts b/frontend/src/lang/modules/ms.ts index 935a8fb5e..3149eb879 100644 --- a/frontend/src/lang/modules/ms.ts +++ b/frontend/src/lang/modules/ms.ts @@ -7033,6 +7033,8 @@ const message = { }, }, dependencies: 'Kebergantungan', + architectureUnsupported: + 'Seni bina sistem semasa {0} tidak disokong. Ciri VM kini hanya menyokong AMD64 dan ARM64.', dependencyPurpose: 'Tujuan', dependencyPurposeMap: { libvirt: 'Menyediakan perkhidmatan pengurusan VM untuk kitar hayat dan penjadualan sumber.', diff --git a/frontend/src/lang/modules/pt-br.ts b/frontend/src/lang/modules/pt-br.ts index d0c5e847e..0cd8e933b 100644 --- a/frontend/src/lang/modules/pt-br.ts +++ b/frontend/src/lang/modules/pt-br.ts @@ -7075,6 +7075,8 @@ const message = { }, }, dependencies: 'Dependências', + architectureUnsupported: + 'A arquitetura atual do sistema, {0}, não é compatível. Os recursos de VM aceitam apenas AMD64 e ARM64.', dependencyPurpose: 'Finalidade', dependencyPurposeMap: { libvirt: diff --git a/frontend/src/lang/modules/ru.ts b/frontend/src/lang/modules/ru.ts index 32c1bda2a..8762daec1 100644 --- a/frontend/src/lang/modules/ru.ts +++ b/frontend/src/lang/modules/ru.ts @@ -7041,6 +7041,8 @@ const message = { }, }, dependencies: 'Зависимости', + architectureUnsupported: + 'Текущая архитектура системы {0} не поддерживается. Функции ВМ поддерживают только AMD64 и ARM64.', dependencyPurpose: 'Назначение', dependencyPurposeMap: { libvirt: 'Предоставляет службу управления ВМ, отвечает за жизненный цикл и распределение ресурсов.', diff --git a/frontend/src/lang/modules/tr.ts b/frontend/src/lang/modules/tr.ts index 74ee7d6d1..946c3efd9 100644 --- a/frontend/src/lang/modules/tr.ts +++ b/frontend/src/lang/modules/tr.ts @@ -7037,6 +7037,8 @@ const message = { }, }, dependencies: 'Bağımlılıklar', + architectureUnsupported: + 'Mevcut sistem mimarisi {0} desteklenmiyor. VM özellikleri şu anda yalnızca AMD64 ve ARM64 mimarilerini destekliyor.', dependencyPurpose: 'Amaç', dependencyPurposeMap: { libvirt: 'Yaşam döngüsü denetimi ve kaynak zamanlaması için VM yönetim hizmetleri sağlar.', diff --git a/frontend/src/lang/modules/zh-Hant.ts b/frontend/src/lang/modules/zh-Hant.ts index 15478b1ab..63a632299 100644 --- a/frontend/src/lang/modules/zh-Hant.ts +++ b/frontend/src/lang/modules/zh-Hant.ts @@ -6449,6 +6449,7 @@ const message = { }, }, dependencies: '依賴', + architectureUnsupported: '目前系統架構 {0} 暫不支援虛擬機功能,目前僅支援 AMD64 和 ARM64。', dependencyPurpose: '作用', dependencyPurposeMap: { libvirt: '提供虛擬機管理服務,負責虛擬機生命週期和資源調度。', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index 56d7928a7..54257f85d 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -6514,6 +6514,7 @@ const message = { }, overview: '概览', dependencies: '依赖', + architectureUnsupported: '当前系统架构 {0} 暂不支持虚拟机功能,目前仅支持 AMD64 和 ARM64。', dependencyPurpose: '作用', dependencyPurposeMap: { libvirt: '提供虚拟机管理服务,负责虚拟机生命周期和资源调度。',