mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2024-11-27 20:49:03 +08:00
parent
c49c4b7863
commit
39b8de7ada
@ -8,6 +8,22 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// @Tags Dashboard
|
||||
// @Summary Load os info
|
||||
// @Description 获取服务器基础数据
|
||||
// @Accept json
|
||||
// @Success 200 {object} dto.OsInfo
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /dashboard/base/os [get]
|
||||
func (b *BaseApi) LoadDashboardOsInfo(c *gin.Context) {
|
||||
data, err := dashboardService.LoadOsInfo()
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, data)
|
||||
}
|
||||
|
||||
// @Tags Dashboard
|
||||
// @Summary Load dashboard base info
|
||||
// @Description 获取首页基础数据
|
||||
|
@ -24,6 +24,14 @@ type DashboardBase struct {
|
||||
CurrentInfo DashboardCurrent `json:"currentInfo"`
|
||||
}
|
||||
|
||||
type OsInfo struct {
|
||||
OS string `json:"os"`
|
||||
Platform string `json:"platform"`
|
||||
PlatformFamily string `json:"platformFamily"`
|
||||
KernelArch string `json:"kernelArch"`
|
||||
KernelVersion string `json:"kernelVersion"`
|
||||
}
|
||||
|
||||
type DashboardCurrent struct {
|
||||
Uptime uint64 `json:"uptime"`
|
||||
TimeSinceUptime string `json:"timeSinceUptime"`
|
||||
|
@ -22,6 +22,7 @@ import (
|
||||
type DashboardService struct{}
|
||||
|
||||
type IDashboardService interface {
|
||||
LoadOsInfo() (*dto.OsInfo, error)
|
||||
LoadBaseInfo(ioOption string, netOption string) (*dto.DashboardBase, error)
|
||||
LoadCurrentInfo(ioOption string, netOption string) *dto.DashboardCurrent
|
||||
|
||||
@ -49,6 +50,27 @@ func (u *DashboardService) Restart(operation string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *DashboardService) LoadOsInfo() (*dto.OsInfo, error) {
|
||||
var baseInfo dto.OsInfo
|
||||
hostInfo, err := host.Info()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
baseInfo.OS = hostInfo.OS
|
||||
baseInfo.Platform = hostInfo.Platform
|
||||
baseInfo.PlatformFamily = hostInfo.PlatformFamily
|
||||
baseInfo.KernelArch = hostInfo.KernelArch
|
||||
baseInfo.KernelVersion = hostInfo.KernelVersion
|
||||
|
||||
if baseInfo.KernelArch == "armv7l" {
|
||||
baseInfo.KernelArch = "armv7"
|
||||
}
|
||||
if baseInfo.KernelArch == "x86_64" {
|
||||
baseInfo.KernelArch = "amd64"
|
||||
}
|
||||
return &baseInfo, nil
|
||||
}
|
||||
|
||||
func (u *DashboardService) LoadBaseInfo(ioOption string, netOption string) (*dto.DashboardBase, error) {
|
||||
var baseInfo dto.DashboardBase
|
||||
hostInfo, err := host.Info()
|
||||
|
@ -19,6 +19,7 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/files"
|
||||
"github.com/jinzhu/copier"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/shirou/gopsutil/v3/host"
|
||||
)
|
||||
|
||||
type SnapshotService struct {
|
||||
@ -134,6 +135,9 @@ func (u *SnapshotService) SnapshotRecover(req dto.SnapshotRecover) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if hasOs(snap.Name) && !strings.Contains(snap.Name, loadOs()) {
|
||||
return fmt.Errorf("Restoring snapshots(%s) between different server architectures(%s) is not supported.", snap.Name, loadOs())
|
||||
}
|
||||
if !req.IsNew && len(snap.InterruptStep) != 0 && len(snap.RollbackStatus) != 0 {
|
||||
return fmt.Errorf("the snapshot has been rolled back and cannot be restored again")
|
||||
}
|
||||
@ -189,9 +193,10 @@ func (u *SnapshotService) HandleSnapshot(isCronjob bool, logPath string, req dto
|
||||
|
||||
if req.ID == 0 {
|
||||
versionItem, _ := settingRepo.Get(settingRepo.WithByKey("SystemVersion"))
|
||||
name := fmt.Sprintf("1panel_%s_%s", versionItem.Value, timeNow)
|
||||
|
||||
name := fmt.Sprintf("1panel_%s_%s_%s", versionItem.Value, loadOs(), timeNow)
|
||||
if isCronjob {
|
||||
name = fmt.Sprintf("snapshot_1panel_%s_%s", versionItem.Value, timeNow)
|
||||
name = fmt.Sprintf("snapshot_1panel_%s_%s_%s", versionItem.Value, loadOs(), timeNow)
|
||||
}
|
||||
rootDir = path.Join(localDir, "system", name)
|
||||
|
||||
@ -481,3 +486,23 @@ func loadLogByStatus(status model.SnapshotStatus, logPath string) {
|
||||
defer file.Close()
|
||||
_, _ = file.Write([]byte(logs))
|
||||
}
|
||||
|
||||
func hasOs(name string) bool {
|
||||
return strings.Contains(name, "amd64") ||
|
||||
strings.Contains(name, "arm64") ||
|
||||
strings.Contains(name, "armv7") ||
|
||||
strings.Contains(name, "ppc64le") ||
|
||||
strings.Contains(name, "s390x")
|
||||
}
|
||||
|
||||
func loadOs() string {
|
||||
hostInfo, _ := host.Info()
|
||||
switch hostInfo.KernelArch {
|
||||
case "x86_64":
|
||||
return "amd64"
|
||||
case "armv7l":
|
||||
return "armv7"
|
||||
default:
|
||||
return hostInfo.KernelArch
|
||||
}
|
||||
}
|
||||
|
@ -3830,6 +3830,31 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/dashboard/base/os": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "获取服务器基础数据",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Dashboard"
|
||||
],
|
||||
"summary": "Load os info",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/dto.OsInfo"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/dashboard/current/:ioOption/:netOption": {
|
||||
"get": {
|
||||
"security": [
|
||||
@ -16828,6 +16853,26 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"dto.OsInfo": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"kernelArch": {
|
||||
"type": "string"
|
||||
},
|
||||
"kernelVersion": {
|
||||
"type": "string"
|
||||
},
|
||||
"os": {
|
||||
"type": "string"
|
||||
},
|
||||
"platform": {
|
||||
"type": "string"
|
||||
},
|
||||
"platformFamily": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dto.PageContainer": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
@ -18967,7 +19012,6 @@ const docTemplate = `{
|
||||
"request.FileEdit": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"content",
|
||||
"path"
|
||||
],
|
||||
"properties": {
|
||||
|
@ -3823,6 +3823,31 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/dashboard/base/os": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "获取服务器基础数据",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Dashboard"
|
||||
],
|
||||
"summary": "Load os info",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/dto.OsInfo"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/dashboard/current/:ioOption/:netOption": {
|
||||
"get": {
|
||||
"security": [
|
||||
@ -16821,6 +16846,26 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"dto.OsInfo": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"kernelArch": {
|
||||
"type": "string"
|
||||
},
|
||||
"kernelVersion": {
|
||||
"type": "string"
|
||||
},
|
||||
"os": {
|
||||
"type": "string"
|
||||
},
|
||||
"platform": {
|
||||
"type": "string"
|
||||
},
|
||||
"platformFamily": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dto.PageContainer": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
@ -18960,7 +19005,6 @@
|
||||
"request.FileEdit": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"content",
|
||||
"path"
|
||||
],
|
||||
"properties": {
|
||||
|
@ -1887,6 +1887,19 @@ definitions:
|
||||
option:
|
||||
type: string
|
||||
type: object
|
||||
dto.OsInfo:
|
||||
properties:
|
||||
kernelArch:
|
||||
type: string
|
||||
kernelVersion:
|
||||
type: string
|
||||
os:
|
||||
type: string
|
||||
platform:
|
||||
type: string
|
||||
platformFamily:
|
||||
type: string
|
||||
type: object
|
||||
dto.PageContainer:
|
||||
properties:
|
||||
excludeAppStore:
|
||||
@ -3319,7 +3332,6 @@ definitions:
|
||||
path:
|
||||
type: string
|
||||
required:
|
||||
- content
|
||||
- path
|
||||
type: object
|
||||
request.FileMove:
|
||||
@ -7412,6 +7424,21 @@ paths:
|
||||
summary: Load dashboard base info
|
||||
tags:
|
||||
- Dashboard
|
||||
/dashboard/base/os:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 获取服务器基础数据
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/dto.OsInfo'
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: Load os info
|
||||
tags:
|
||||
- Dashboard
|
||||
/dashboard/current/:ioOption/:netOption:
|
||||
get:
|
||||
consumes:
|
||||
|
@ -1,4 +1,11 @@
|
||||
export namespace Dashboard {
|
||||
export interface OsInfo {
|
||||
os: string;
|
||||
platform: string;
|
||||
platformFamily: string;
|
||||
kernelArch: string;
|
||||
kernelVersion: string;
|
||||
}
|
||||
export interface BaseInfo {
|
||||
websiteNumber: number;
|
||||
databaseNumber: number;
|
||||
|
@ -1,6 +1,10 @@
|
||||
import http from '@/api';
|
||||
import { Dashboard } from '../interface/dashboard';
|
||||
|
||||
export const loadOsInfo = () => {
|
||||
return http.get<Dashboard.OsInfo>(`/dashboard/base/os`);
|
||||
};
|
||||
|
||||
export const loadBaseInfo = (ioOption: string, netOption: string) => {
|
||||
return http.get<Dashboard.BaseInfo>(`/dashboard/base/${ioOption}/${netOption}`);
|
||||
};
|
||||
|
@ -1405,14 +1405,15 @@ const message = {
|
||||
createSnapshot: 'Create snapshot',
|
||||
importSnapshot: 'Sync snapshot',
|
||||
recover: 'Recover',
|
||||
noRecoverRecord: 'No recovery record has been recorded',
|
||||
lastRecoverAt: 'Last recovery time',
|
||||
lastRollbackAt: 'Last rollback time',
|
||||
noRollbackRecord: 'No rollback record has been recorded',
|
||||
reDownload: 'Download the backup file again',
|
||||
recoverRecord: 'Recover record',
|
||||
recoverHelper:
|
||||
'The recovery is about to start from snapshot {0}, and the recovery needs to restart docker and 1panel service, do you want to continue?',
|
||||
recoverHelper1:
|
||||
'Will start restoring from snapshot {0}, please ensure that the server architecture matches the one where the snapshot was created.',
|
||||
recoverHelper2: 'Restoring snapshots between different server architectures is not supported.',
|
||||
rollback: 'Rollback',
|
||||
rollbackHelper:
|
||||
'This recovery is about to be rolled back, which will replace all the files recovered this time. In the process, docker and 1panel services may need to be restarted. Do you want to continue?',
|
||||
|
@ -1246,17 +1246,14 @@ const message = {
|
||||
createSnapshot: '創建快照',
|
||||
importSnapshot: '同步快照',
|
||||
recover: '恢復',
|
||||
noRecoverRecord: '暫無恢復記錄',
|
||||
lastRecoverAt: '上次恢復時間',
|
||||
lastRollbackAt: '上次回滾時間',
|
||||
noRollbackRecord: '暫無回滾記錄',
|
||||
reDownload: '重新下載備份文件',
|
||||
statusAll: '全部',
|
||||
statusSuccess: '成功',
|
||||
statusFailed: '失敗',
|
||||
versionChange: '版本變化',
|
||||
snapshotFrom: '快照存儲位置',
|
||||
recoverHelper: '即將從快照 {0} 開始恢復,恢復需要重啟 docker 以及 1panel 服務,是否繼續?',
|
||||
recoverHelper1: '即將從快照 {0} 開始恢復,請確保伺服器架構與創建快照伺服器架構信息保持一致。',
|
||||
recoverHelper2: '不支持在不同伺服器架構之間進行快照恢復操作。',
|
||||
rollback: '回滾',
|
||||
rollbackHelper:
|
||||
'即將回滾本次恢復,回滾將替換所有本次恢復的文件,過程中可能需要重啟 docker 以及 1panel 服務,是否繼續?',
|
||||
|
@ -1247,17 +1247,14 @@ const message = {
|
||||
createSnapshot: '创建快照',
|
||||
importSnapshot: '同步快照',
|
||||
recover: '恢复',
|
||||
noRecoverRecord: '暂无恢复记录',
|
||||
lastRecoverAt: '上次恢复时间',
|
||||
lastRollbackAt: '上次回滚时间',
|
||||
noRollbackRecord: '暂无回滚记录',
|
||||
reDownload: '重新下载备份文件',
|
||||
statusAll: '全部',
|
||||
statusSuccess: '成功',
|
||||
statusFailed: '失败',
|
||||
versionChange: '版本变化',
|
||||
snapshotFrom: '快照存储位置',
|
||||
recoverHelper: '即将从快照 {0} 开始恢复,恢复需要重启 docker 以及 1panel 服务,是否继续?',
|
||||
recoverHelper1: '即将从快照 {0} 开始恢复,请确保服务器架构与创建快照服务器架构信息保持一致。',
|
||||
recoverHelper2: '不支持在不同服务器架构之间进行快照恢复操作。',
|
||||
rollback: '回滚',
|
||||
rollbackHelper:
|
||||
'即将回滚本次恢复,回滚将替换所有本次恢复的文件,过程中可能需要重启 docker 以及 1panel 服务,是否继续?',
|
||||
|
@ -172,7 +172,8 @@ import { ElMessageBox } from 'element-plus';
|
||||
import i18n from '@/lang';
|
||||
import DrawerHeader from '@/components/drawer-header/index.vue';
|
||||
import { snapshotRecover, snapshotRollback } from '@/api/modules/setting';
|
||||
import { MsgSuccess } from '@/utils/message';
|
||||
import { MsgError, MsgSuccess } from '@/utils/message';
|
||||
import { loadOsInfo } from '@/api/modules/dashboard';
|
||||
|
||||
const drawerVisible = ref(false);
|
||||
const snapInfo = ref();
|
||||
@ -210,7 +211,27 @@ const doRecover = async (isNew: boolean) => {
|
||||
};
|
||||
|
||||
const recoverSnapshot = async (isNew: boolean) => {
|
||||
ElMessageBox.confirm(i18n.global.t('setting.recoverHelper', [snapInfo.value.name]), {
|
||||
let msg = i18n.global.t('setting.recoverHelper', [snapInfo.value.name]);
|
||||
if (
|
||||
snapInfo.value.name.indexOf('amd64') === -1 &&
|
||||
snapInfo.value.name.indexOf('arm64') === -1 &&
|
||||
snapInfo.value.name.indexOf('armv7') === -1 &&
|
||||
snapInfo.value.name.indexOf('ppc64le') === -1 &&
|
||||
snapInfo.value.name.indexOf('s390x') === -1
|
||||
) {
|
||||
msg = i18n.global.t('setting.recoverHelper1', [snapInfo.value.name]);
|
||||
} else {
|
||||
const res = await loadOsInfo();
|
||||
let osVal = res.data.kernelArch;
|
||||
if (osVal === '') {
|
||||
msg = i18n.global.t('setting.recoverHelper1', [snapInfo.value.name]);
|
||||
} else if (snapInfo.value.name.indexOf(osVal) === -1) {
|
||||
MsgError(i18n.global.t('setting.recoverHelper2'));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ElMessageBox.confirm(msg, i18n.global.t('commons.button.recover'), {
|
||||
confirmButtonText: i18n.global.t('commons.button.confirm'),
|
||||
cancelButtonText: i18n.global.t('commons.button.cancel'),
|
||||
type: 'info',
|
||||
|
Loading…
Reference in New Issue
Block a user