mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-12-11 21:06:08 +08:00
feat: Scheduled tasks support backing up MySQL cluster databases (#9526)
This commit is contained in:
parent
70f63090fe
commit
75bfc3a114
16 changed files with 42 additions and 18 deletions
|
|
@ -658,10 +658,7 @@ func upgradeInstall(req request.AppInstallUpgrade) error {
|
|||
}
|
||||
|
||||
command := exec.Command("/bin/bash", "-c", fmt.Sprintf("cp -rn %s/* %s || true", detailDir, install.GetPath()))
|
||||
stdout, _ := command.CombinedOutput()
|
||||
if stdout != nil {
|
||||
t.Logger.Printf("upgrade app [%s] [%s] cp file log : %s ", install.App.Key, install.Name, string(stdout))
|
||||
}
|
||||
_, _ = command.CombinedOutput()
|
||||
sourceScripts := path.Join(detailDir, "scripts")
|
||||
if fileOp.Stat(sourceScripts) {
|
||||
dstScripts := path.Join(install.GetPath(), "scripts")
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ func (u *CronjobService) handleDatabase(cronjob model.Cronjob, startTime time.Ti
|
|||
|
||||
backupDir := path.Join(global.Dir.TmpDir, fmt.Sprintf("database/%s/%s/%s", dbInfo.DBType, record.Name, dbInfo.Name))
|
||||
record.FileName = fmt.Sprintf("db_%s_%s.sql.gz", dbInfo.Name, startTime.Format(constant.DateTimeSlimLayout)+common.RandStrAndNum(5))
|
||||
if cronjob.DBType == "mysql" || cronjob.DBType == "mariadb" {
|
||||
if cronjob.DBType == "mysql" || cronjob.DBType == "mariadb" || cronjob.DBType == "mysql-cluster" {
|
||||
if err := doMysqlBackup(dbInfo, backupDir, record.FileName); err != nil {
|
||||
if retry < int(cronjob.RetryTimes) || !cronjob.IgnoreErr {
|
||||
retry++
|
||||
|
|
@ -354,7 +354,7 @@ type DatabaseHelper struct {
|
|||
func loadDbsForJob(cronjob model.Cronjob) []DatabaseHelper {
|
||||
var dbs []DatabaseHelper
|
||||
if cronjob.DBName == "all" {
|
||||
if cronjob.DBType == "mysql" || cronjob.DBType == "mariadb" {
|
||||
if cronjob.DBType == "mysql" || cronjob.DBType == "mariadb" || cronjob.DBType == "mysql-cluster" {
|
||||
databaseService := NewIDatabaseService()
|
||||
mysqlItems, _ := databaseService.LoadItems(cronjob.DBType)
|
||||
for _, mysql := range mysqlItems {
|
||||
|
|
@ -381,7 +381,7 @@ func loadDbsForJob(cronjob model.Cronjob) []DatabaseHelper {
|
|||
dbNames := strings.Split(cronjob.DBName, ",")
|
||||
for _, name := range dbNames {
|
||||
itemID, _ := strconv.Atoi(name)
|
||||
if cronjob.DBType == "mysql" || cronjob.DBType == "mariadb" {
|
||||
if cronjob.DBType == "mysql" || cronjob.DBType == "mariadb" || cronjob.DBType == "mysql-cluster" {
|
||||
mysqlItem, _ := mysqlRepo.Get(repo.WithByID(uint(itemID)))
|
||||
dbs = append(dbs, DatabaseHelper{
|
||||
ID: mysqlItem.ID,
|
||||
|
|
|
|||
|
|
@ -164,6 +164,10 @@ var WebUrlMap = map[string]struct{}{
|
|||
"/xpack/node": {},
|
||||
"/xpack/exchange/file": {},
|
||||
"/xpack/app": {},
|
||||
|
||||
"/xpack/cluster/mysql": {},
|
||||
"/xpack/cluster/postgres": {},
|
||||
"/xpack/cluster/redis": {},
|
||||
}
|
||||
|
||||
var DynamicRoutes = []string{
|
||||
|
|
|
|||
|
|
@ -23,4 +23,5 @@ const (
|
|||
StatusInstalling = "Installing"
|
||||
StatusNormal = "Normal"
|
||||
StatusDeleted = "Deleted"
|
||||
StatusLoading = "Loading"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -201,4 +201,6 @@ ErrExpiredToken: 'Token has expired, please reset and scan again.'
|
|||
|
||||
#cluster
|
||||
ErrMasterDelete: "Unable to delete the master node, please delete the slave nodes first."
|
||||
ClusterNameIsExist: "Cluster name already exists."
|
||||
ClusterNameIsExist: "Cluster name already exists."
|
||||
AppStatusUnHealthy: "Application status acquisition is abnormal, please check the installation node status in the node list."
|
||||
MasterNodePortNotAvailable: "Node {{ .name }} port {{ .port }} connectivity verification failed, please check firewall/security group settings and master node status."
|
||||
|
|
@ -202,4 +202,6 @@ ErrExpiredToken: 'トークンの有効期限が切れました。リセット
|
|||
|
||||
#cluster
|
||||
ErrMasterDelete: "マスターノードを削除できません。スレーブノードを先に削除してください。"
|
||||
ClusterNameIsExist: "クラスタ名は既に存在します。"
|
||||
ClusterNameIsExist: "クラスタ名は既に存在します。"
|
||||
AppStatusUnHealthy: "アプリケーションのステータス取得が異常です。ノードリストでインストールノードのステータスを確認してください。"
|
||||
MasterNodePortNotAvailable: "ノード {{ .name }} のポート {{ .port }} の接続性検証が失敗しました。ファイアウォール/セキュリティグループの設定とマスターノードのステータスを確認してください。"
|
||||
|
|
@ -201,4 +201,6 @@ ErrExpiredToken: '토큰이 만료되었습니다. 재설정 후 다시 스캔
|
|||
|
||||
#cluster
|
||||
ErrMasterDelete: "마스터 노드를 삭제할 수 없습니다. 슬레이브 노드를 먼저 삭제하세요."
|
||||
ClusterNameIsExist: "클러스터 이름이 이미 존재합니다."
|
||||
ClusterNameIsExist: "클러스터 이름이 이미 존재합니다."
|
||||
AppStatusUnHealthy: "애플리케이션 상태 획득이 비정상입니다. 노드 목록에서 설치 노드 상태를 확인하세요."
|
||||
MasterNodePortNotAvailable: "노드 {{ .name }} 포트 {{ .port }} 연결성 검증에 실패했습니다. 방화벽/보안 그룹 설정 및 마스터 노드 상태를 확인하세요."
|
||||
|
|
@ -196,4 +196,6 @@ SystemMode: "Mod: "
|
|||
|
||||
#cluster
|
||||
ErrMasterDelete: "Tidak dapat menghapus nod utama, sila hapuskan nod perantara dahulu."
|
||||
ClusterNameIsExist: "Nama kluster sudah wujud."
|
||||
ClusterNameIsExist: "Nama kluster sudah wujud."
|
||||
AppStatusUnHealthy: "Pengambilan status aplikasi tidak normal, sila periksa status nod pemasangan dalam senarai nod."
|
||||
MasterNodePortNotAvailable: "Pengesahan kesambungan pelabuhan {{ .name }} nod {{ .port }} gagal, sila periksa tetapan firewall/kumpulan keselamatan dan status nod utama."
|
||||
|
|
@ -201,4 +201,6 @@ ErrExpiredToken: 'O token expirou, por favor, reinicie e escaneie novamente.'
|
|||
|
||||
#cluster
|
||||
ErrMasterDelete: "Não é possível excluir o nó mestre, exclua os nós escravos primeiro."
|
||||
ClusterNameIsExist: "O nome do cluster já existe."
|
||||
ClusterNameIsExist: "O nome do cluster já existe."
|
||||
AppStatusUnHealthy: "A aquisição do status do aplicativo está anormal, verifique o status dos nós de instalação na lista de nós."
|
||||
MasterNodePortNotAvailable: "A verificação de conectividade da porta {{ .port }} do nó {{ .name }} falhou, verifique as configurações de firewall/grupo de segurança e o status do nó mestre."
|
||||
|
|
@ -201,4 +201,6 @@ ErrExpiredToken: 'Токен истек, пожалуйста, сбросьте
|
|||
|
||||
#cluster
|
||||
ErrMasterDelete: "Невозможно удалить основной узел, сначала удалите подчиненные узлы."
|
||||
ClusterNameIsExist: "Имя кластера уже существует."
|
||||
ClusterNameIsExist: "Имя кластера уже существует."
|
||||
AppStatusUnHealthy: "Получение статуса приложения аномально, пожалуйста, проверьте статус узлов установки в списке узлов."
|
||||
MasterNodePortNotAvailable: "Проверка подключения порта {{ .port }} узла {{ .name }} не удалась, пожалуйста, проверьте настройки брандмауэра/группы безопасности и статус главного узла."
|
||||
|
|
@ -199,4 +199,6 @@ ErrExpiredToken: 'Token süresi dolmuş, lütfen sıfırlayın ve tekrar tarayı
|
|||
|
||||
#cluster
|
||||
ErrMasterDelete: "Ana düğümü silinemiyor, lütfen önce alt düğümleri silin."
|
||||
ClusterNameIsExist: "Küme adı zaten var."
|
||||
ClusterNameIsExist: "Küme adı zaten var."
|
||||
AppStatusUnHealthy: "Uygulama durumu alımı anormal, lütfen düğüm listesindeki yükleme düğümü durumunu kontrol edin."
|
||||
MasterNodePortNotAvailable: "Düğüm {{ .name }} portu {{ .port }} bağlantı doğrulaması başarısız oldu, lütfen güvenlik duvarı/güvenlik grubu ayarlarını ve ana düğüm durumunu kontrol edin."
|
||||
|
|
@ -210,4 +210,6 @@ ErrExpiredToken: '令牌過期,請重設後再次掃碼'
|
|||
|
||||
#cluster
|
||||
ErrMasterDelete: "無法刪除主節點,請先刪除從節點。"
|
||||
ClusterNameIsExist: "集群名稱已存在。"
|
||||
ClusterNameIsExist: "集群名稱已存在。"
|
||||
AppStatusUnHealthy: "應用獲取狀態異常,請在節點列表檢查安裝節點狀態。"
|
||||
MasterNodePortNotAvailable: "節點 {{ .name }} 端口 {{ .port }} 連通性校驗失敗,請檢查防火牆/安全組設置和主節點狀態。"
|
||||
|
|
@ -210,4 +210,6 @@ ErrExpiredToken: '令牌过期,请重置后再次扫码'
|
|||
|
||||
#cluster
|
||||
ErrMasterDelete: "无法删除主节点,请先删除从节点"
|
||||
ClusterNameIsExist: "集群名称已存在"
|
||||
ClusterNameIsExist: "集群名称已存在"
|
||||
AppStatusUnHealthy: "应用获取状态异常,请在节点列表检查安装节点状态"
|
||||
MasterNodePortNotAvailable: "节点 {{ .name }} 端口 {{ .port }} 连通性校验失败,请检查防火墙/安全组设置和主节点状态"
|
||||
|
|
@ -73,8 +73,9 @@ export const getAppInstalled = (search: App.AppInstalledSearch) => {
|
|||
return http.post<ResPage<App.AppInstalled>>('apps/installed/search', search);
|
||||
};
|
||||
|
||||
export const getAppInstalledByID = (installID: number, node: string) => {
|
||||
return http.get<App.AppInstalledInfo>(`apps/installed/info/${installID}?operateNode=${node}`);
|
||||
export const getAppInstalledByID = (installID: number, node?: string) => {
|
||||
const params = node ? `?operateNode=${node}` : '';
|
||||
return http.get<App.AppInstalledInfo>(`apps/installed/info/${installID}${params}`);
|
||||
};
|
||||
|
||||
export const installedOp = (op: App.AppInstalledOp) => {
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@ const loadingStatus = [
|
|||
'sending',
|
||||
'waiting',
|
||||
'executing',
|
||||
'loading',
|
||||
];
|
||||
|
||||
const stopStatus = ['stopped', 'exited', 'disable'];
|
||||
|
|
|
|||
|
|
@ -282,8 +282,10 @@
|
|||
<el-form-item :label="$t('cronjob.database')">
|
||||
<el-select v-model="form.dbType" @change="loadDatabases">
|
||||
<el-option label="MySQL" value="mysql" />
|
||||
<el-option label="MySQL-Cluster" value="mysql-cluster" />
|
||||
<el-option label="Mariadb" value="mariadb" />
|
||||
<el-option label="PostgreSQL" value="postgresql" />
|
||||
<el-option label="PostgreSQL-Cluster" value="postgresql-cluster" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</LayoutCol>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue