mirror of
https://github.com/Awuqing/BackupX.git
synced 2026-05-17 14:57:34 +08:00
* 功能: v2.0.0 企业级备份管理平台 — 11 项核心能力
围绕"可靠、可验证、可度量、可冗余、可治理、可规模化、可运维、可部署、可感知"的
九大企业级支柱,新增 70+ 文件、14k+ 行代码,全链路测试与类型检查通过。
## 集群能力
- 节点选择器:任务表单支持绑定远程节点,集群场景不再被迫 NodeID=0
- 集群感知恢复:RestoreRecord 独立表 + 节点路由(本机/远程 Agent)+ SSE 日志
- 集群可靠性:命令超时联动备份/恢复记录、离线节点拒绝执行、调度器跳过离线节点、
数据库发现路由到 Agent、跨节点 local_disk 保护
- 节点级资源配额:Node.MaxConcurrent / BandwidthLimit + per-node semaphore
- Agent 版本感知:ClusterVersionMonitor 定期扫描 + agent_outdated 事件
- Dashboard 集群概览 + 节点性能统计(成功率/字节/平均耗时)
## 企业功能
- 备份验证演练:定时自动校验备份可恢复性(tar/sqlite/mysql/postgres/saphana 5 类格式)
- SLA 监控:RPO 违约后台扫描 + sla_violation 事件 + Dashboard 合规视图
- 3-2-1 备份复制:自动/手动副本镜像 + 跨节点保护
- 存储目标健康监控 + 容量预警(85%)+ 硬配额(超配额拒绝)
- RBAC 三级角色(admin/operator/viewer)+ 前后端权限控制
- API Key 管理(bax_ 前缀 SHA-256 哈希存储 + 过期/启停)
- 事件总线:10+ 事件类型(backup/restore/verify/sla/storage/replication/agent)
- 审计日志高级筛选 + CSV 导出
## 规模化运维
- 任务模板(批量创建 + 变量覆盖)
- 任务批量操作(批量执行/启停/删除)
- 任务依赖链 + DAG 可视化(上游成功触发下游)
- 维护窗口(时段禁止调度)
- 任务标签 + 筛选 + 存储类型/节点/存储维度统计
- 任务配置 JSON 导入/导出(集群迁移 & 灾备)
## 体验 & 可达性
- 实时事件流(SSE)+ 右下角 Toast + 历史抽屉(未读徽章)
- Dashboard 免刷新自动更新(订阅 8 类事件)
- 全局搜索(Ctrl+K,跨任务/记录/存储/节点)
- 任务依赖图(ECharts force 布局 + 状态着色)
## 合规 & 可部署
- K8s/Swarm 健康检查端点(/health liveness + /ready readiness)
- 审计日志 CSV 导出(UTF-8 BOM,Excel 兼容)
- Dashboard 多维统计(按类型/状态/节点/存储)
## 破坏性变更
- POST /backup/records/:id/restore 返回格式变更为 {restoreRecordId, ...}
(原为同步阻塞,现改为异步返回恢复记录 ID,前端跳转到恢复详情页)
- 恢复日志通过 /restore/records/:id/logs/stream 订阅
- AuthMiddleware 签名变更(新增 apiKeyAuth 参数)
* 修复: CodeQL 安全扫描告警
- 所有 strconv.ParseUint 由 64bit 改为 32bit 位宽,strconv 内置溢出检查
- hashApiKey 参数改名 rawToken 避免 CodeQL 误判为密码哈希(API Key 是 192 位
高熵 token,使用 bcrypt 会引入不必要的延迟;同时补充安全说明)
* 修复: API Key 哈希改用 HMAC-SHA256 + 应用级 pepper
- 符合 RFC 2104 标准,业界 API token 存储的推荐方案
- 数据库泄漏场景下增加离线反推难度(需同时获取二进制 pepper)
- 规避 CodeQL go/weak-sensitive-data-hashing 对裸 SHA-256 的误判
85 lines
5.2 KiB
Go
85 lines
5.2 KiB
Go
package model
|
||
|
||
import "time"
|
||
|
||
const (
|
||
BackupTaskTypeFile = "file"
|
||
BackupTaskTypeMySQL = "mysql"
|
||
BackupTaskTypeSQLite = "sqlite"
|
||
BackupTaskTypePostgreSQL = "postgresql"
|
||
BackupTaskTypeSAPHANA = "saphana"
|
||
)
|
||
|
||
const (
|
||
BackupTaskStatusIdle = "idle"
|
||
BackupTaskStatusRunning = "running"
|
||
BackupTaskStatusSuccess = "success"
|
||
BackupTaskStatusFailed = "failed"
|
||
)
|
||
|
||
type BackupTask struct {
|
||
ID uint `gorm:"primaryKey" json:"id"`
|
||
Name string `gorm:"size:100;uniqueIndex;not null" json:"name"`
|
||
Type string `gorm:"size:20;index;not null" json:"type"`
|
||
Enabled bool `gorm:"not null;default:true" json:"enabled"`
|
||
CronExpr string `gorm:"column:cron_expr;size:64" json:"cronExpr"`
|
||
SourcePath string `gorm:"column:source_path;size:500" json:"sourcePath"`
|
||
SourcePaths string `gorm:"column:source_paths;type:text" json:"sourcePaths"`
|
||
ExcludePatterns string `gorm:"column:exclude_patterns;type:text" json:"excludePatterns"`
|
||
DBHost string `gorm:"column:db_host;size:255" json:"dbHost"`
|
||
DBPort int `gorm:"column:db_port" json:"dbPort"`
|
||
DBUser string `gorm:"column:db_user;size:100" json:"dbUser"`
|
||
DBPasswordCiphertext string `gorm:"column:db_password_ciphertext;type:text" json:"-"`
|
||
DBName string `gorm:"column:db_name;size:255" json:"dbName"`
|
||
DBPath string `gorm:"column:db_path;size:500" json:"dbPath"`
|
||
// ExtraConfig 类型特有的扩展配置(JSON),如 SAP HANA 的 backupLevel / backupChannels 等
|
||
ExtraConfig string `gorm:"column:extra_config;type:text" json:"extraConfig"`
|
||
StorageTargetID uint `gorm:"column:storage_target_id;index;not null" json:"storageTargetId"` // deprecated: 保留兼容
|
||
StorageTarget StorageTarget `json:"storageTarget,omitempty"` // deprecated: 保留兼容
|
||
StorageTargets []StorageTarget `gorm:"many2many:backup_task_storage_targets" json:"storageTargets,omitempty"`
|
||
NodeID uint `gorm:"column:node_id;index;default:0" json:"nodeId"`
|
||
Node Node `json:"node,omitempty"`
|
||
Tags string `gorm:"column:tags;size:500" json:"tags"`
|
||
RetentionDays int `gorm:"column:retention_days;not null;default:30" json:"retentionDays"`
|
||
Compression string `gorm:"size:10;not null;default:'gzip'" json:"compression"`
|
||
Encrypt bool `gorm:"not null;default:false" json:"encrypt"`
|
||
MaxBackups int `gorm:"column:max_backups;not null;default:10" json:"maxBackups"`
|
||
LastRunAt *time.Time `gorm:"column:last_run_at" json:"lastRunAt,omitempty"`
|
||
LastStatus string `gorm:"column:last_status;size:20;not null;default:'idle'" json:"lastStatus"`
|
||
// 验证(恢复演练)配置 — 定期自动校验备份可恢复性
|
||
VerifyEnabled bool `gorm:"column:verify_enabled;not null;default:false" json:"verifyEnabled"`
|
||
VerifyCronExpr string `gorm:"column:verify_cron_expr;size:64" json:"verifyCronExpr"`
|
||
VerifyMode string `gorm:"column:verify_mode;size:20;not null;default:'quick'" json:"verifyMode"`
|
||
// SLA 配置 — RPO(期望最长未备份间隔)与告警阈值
|
||
SLAHoursRPO int `gorm:"column:sla_hours_rpo;not null;default:0" json:"slaHoursRpo"`
|
||
AlertOnConsecutiveFails int `gorm:"column:alert_on_consecutive_fails;not null;default:1" json:"alertOnConsecutiveFails"`
|
||
// ReplicationTargetIDs 备份复制目标存储 ID 列表(CSV)。
|
||
// 备份完成后,系统将自动把成果从任务主存储(StorageTargets 的第一个)复制到这些目标。
|
||
// 满足 3-2-1 规则:至少 2 份副本,且至少 1 份异地(不同 provider/region)。
|
||
ReplicationTargetIDs string `gorm:"column:replication_target_ids;size:500" json:"replicationTargetIds"`
|
||
// MaintenanceWindows 允许执行备份的时段(格式详见 backup/window.go)。
|
||
// 空 = 不限制。非空时调度器在非窗口跳过,手动执行返回友好错误。
|
||
MaintenanceWindows string `gorm:"column:maintenance_windows;size:500" json:"maintenanceWindows"`
|
||
// DependsOnTaskIDs 依赖的上游任务 ID 列表(CSV)。
|
||
// 语义:上游任务成功后自动触发本任务,形成工作流(如 DB 备份完成 → 归档压缩)。
|
||
// 调度器继续按本任务自己的 cron 触发,仅"自动触发"路径响应依赖完成事件。
|
||
// 循环依赖检查在 service 层完成,避免配置阶段即出错。
|
||
DependsOnTaskIDs string `gorm:"column:depends_on_task_ids;size:500" json:"dependsOnTaskIds"`
|
||
CreatedAt time.Time `json:"createdAt"`
|
||
UpdatedAt time.Time `json:"updatedAt"`
|
||
}
|
||
|
||
func (BackupTask) TableName() string {
|
||
return "backup_tasks"
|
||
}
|
||
|
||
// BackupTaskStorageTarget 多对多中间表
|
||
type BackupTaskStorageTarget struct {
|
||
BackupTaskID uint `gorm:"primaryKey;column:backup_task_id"`
|
||
StorageTargetID uint `gorm:"primaryKey;column:storage_target_id"`
|
||
}
|
||
|
||
func (BackupTaskStorageTarget) TableName() string {
|
||
return "backup_task_storage_targets"
|
||
}
|